1 :
デフォルトの名無しさん :
02/08/14 18:01 文法が汚くてもいいから、懐の広い言語を望むあなた。そんな
あなたにぴったりの言語、C++。
(´∀`).。o(関連URLは
>>2-5 の辺り)
v(^・^)v < 2!!
すみません。アクセス制御でわからなくなりました。 クラスBとクラスCで、using宣言を行っていますが、これは一見protected属性 の関数print()をpublicなアクセス属性に変換しているように見えるのですが、 そのように考えてよいのでしょうか。 #include <iostream> using namespace std; class A { int i; protected: void print() const { cout << i << endl; } public: A() { i = 111; } }; class B : protected A { public: using A::print; // void print() const { A::print(); } }; class C : protected B { public: using B::print; // void print() const { A::print(); } }; int main() { B b; C c; b.print(); c.print(); }
アクセス属性の変化って許されたっけ?
>>9 変換という言葉は適当ではないかな。
関数などのデフォルト引数のように、継承先で何もされて無いんだったら、
継承元のアクセス制御が適用されるだけという話だと思う。
説明が下手でスマソ。
>>10 >>11 レスありがとうございます。
privateやprotected継承を行っても、using宣言によりメンバをpublic
なスコープに引き出すことにより、継承の本来の意味を変えられる
だけでなく、元々のアクセス属性まで変化させられるので、注意して
使う必要がありそうですね。
>>12 もともと基底でpublicやprotectedなのだから
特に注意はいらないと思うのだが…
>>13 そういう風に考える手もありますね。要するにより細かくアクセス制御
したい時に使うと。
15 :
デフォルトの名無しさん :02/08/15 11:07
17 :
デフォルトの名無しさん :02/08/15 14:13
operator=ってclass外じゃ定義できないの?
class外とは?
できなかったのか?
20 :
デフォルトの名無しさん :02/08/15 14:27
'operator =' は <Unknown> のメンバでなければなりません。 ってエラーがでる。
そりゃあたりまえだ...
22 :
デフォルトの名無しさん :02/08/15 14:32
そうか、できないのか・・・ ちなみにこんなの class AAA{}; AAA operator=(AAA a){return a;} /**************************************************************/ void main(void) { }
> ほとんどの C++ 演算子はクラスのメンバー関数にも, > 通常のクラスのメンバーではない関数にもなりますが, > 以下の演算子は必ずクラスのメンバーでなければなりません。 > > = 演算子 > -> 演算子 > ( ) 演算子 > 型変換 だと。
24 :
デフォルトの名無しさん :02/08/15 14:37
>>22 定義と宣言を分けたいって話なら、そりゃ可能だが。
(;・∀・)ノ スレさん乙変えr〜
28 :
デフォルトの名無しさん :02/08/15 23:13
静的オブジェクトと動的オブジェクトの使い分けってどうされてます?
>>28 静的オブジェクトと動的オブジェクトを混同できるの?
CHoge hoge;と CHoga hoga=new CHoga("hogehoge"); の違いの事なのですが。
そら、 Hoga と Hoge は違おうもん
どういう実装をしているのかわからないけど CHoga hoga=new CHoga("hogehoge"); じゃなくて CHoga* hoga=new CHoga("hogehoge"); じゃないの。
あ、すまいせんそうです。ついjava的な書き方になりますた。
>>33 そうそう、最近全然C++のコードを書かないでJavaの本ばっか
読みまくってたら、オブジェクト生成の書き方がわからなくなってて
焦ったよ^^;
>>30 前者を「静的オブジェクト」とは呼ばんと思うが。
多態前提の OO 設計で出てきたオブジェクトは必然的に後者。値指向の
オブジェクト(複素数やら何やら)だけ例外的に前者。
失礼、質問の仕方が悪かったです。Javaでは静的オブジェクトはなく、全て newしますがC++の場合は静的、動的両方生成される。この場合動的オブジェクトは どんな場合に利用されるのでしょうか?例えばオブジェクトをリストに連結して 実行時に変化があるような場合にのみ利用されるのですか?それとも全てのクラス のインスタンスはnewするのですか? 動的なオブジェクトと静的なオブジェクトのクラスの設計の違いはどのような 特徴なのでしょうか?特に区別はしないのでしょうか?
>>36 だからその意味不明な動的/静的って言葉使うのやめれ。
「Class class;」という形で確保されるオブジェクトには2通りありうる。
1.グローバル、スタティック変数、クラスの静的メンバ。
この場合、オブジェクトの実体は静的なメモリ領域に確保される。
これは普通やらない。理由はコンストラクタ/デストラクタのタイミング。
2.関数内でスタック上に確保される場合。
この場合、「Class class;」とかかれた場所に処理が到達した時点でコンストラクタが実行され、
そこを含むスコープを処理が抜ける瞬間にデストラクタが実行される。
スマートポインタの類は必然的にこの形式で使用される(newで確保すると意味がない)し、
同期オブジェクトなんかのラッパクラスもこういった形で使うものがある。
こういったクラスはスコープを抜ける瞬間に確実に破棄されるという性質を利用してるわけだ。
余りでかいオブジェクトをスタック上に確保しようとするとスタックが足りなくなるのと、
スコープの終わりで破棄される以上一時的なオブジェクトしか作れない点に留意すれば
あとは好きにやればいいと思うが。
設計上の問題は基本的に35以上のことはないと思うのだが、 確かに参照を使えば自動変数でも多態できないこともないが…
39 :
デフォルトの名無しさん :02/08/16 11:10
VS.netのC++でDLLとMFCでのGUI開発を行っています。 1.2MBほどの2つ項目があるタブ区切りテキスト yoshida<TAB>吉田<TAB> 12 yoshimura<TAB>吉村<TAB> 20 . . をクラス class WordFromDic{ string Roma; vector<string> Kana; vector<int> Freq; }; に読み込む処理を行っています 読み込む関数は以下のとおりです MYDLL_API void ReadWordDictionary(char *dic){ ::ifstream WordDic(dic); char buf[256]; while(WordDic.getline(buf,sizeof(buf))){ char *p1 = strtok(buf,"\t"); char *p2 = strtok(NULL,"\t"); char *p3 = strtok(NULL,"\t"); if (!HashDic[p1]){ WordFromDic *temp = new WordFromDic(p1,p2,p3); HashDic[p1] = temp; } else { HashDic[p1]->AddWord(p1,p2,p3); } } } ところがこれが偉く時間がかかってしまうのです。だいたい軌道までに30秒くらいを要する感じです clock()でこの処理の時間をはかってみたところ95600という数値が出ました。 これをもっと早くする方法はないでしょうか? MFCでSTLを使うのはあまりよくないのかなーとも思ったのですが。 さらにメモリの開放時にもやたら時間がかかってしまいます(10秒くらい) MYDLL_API void DeleteWordDictionary(){ for(map<string, class WordFromDic*,less<string> >::iterator i=HashDic.begin(); i!=HashDic.end();i++) { delete i->second; } } この問題についてどなたかアドバイスをいただければと思います
>MFCでSTLを使うのはあまりよくないのかな iostreamは使ってあるが、どこにSTL使ってあるよ?
>40 ええとstringクラスとvectorクラスを使ってます string Roma; vector<string> Kana; vector<int> Freq;
>>40 vectorやらmapやら使ってるでしょ??
>>39 まずはプロファイルを採って、どこで時間を食ってるのか調べてみれば?
44 :
デフォルトの名無しさん :02/08/16 16:15
初歩的な質問で申し訳ないですが、 intの配列型の返り値を持たせるには、 関数はどのような型にすればいいでしょうか。
>>44 void func(std::vector<int>&);
返値を使わずに、引数に参照を渡して、そこに書き込む。
46 :
コギャルとHな出会い :02/08/16 16:23
http://kado7.ug.to/net/ 朝までから騒ぎ!!
小中高生
コギャル〜熟女まで
メル友
i/j/PC/対応
女性の子もたくさん来てね
小中高生大歓迎です
全国デ−トスポット情報も有ります。
全国エステ&ネイル情報あります。
激安携帯情報あります。
int* func() はだめ?
void func(int & n, int * p)
ローカルな配列だとだめですけど。
void func(int & n, int ** p)
std::vector<int> って戻り値にできなかったっけ?
>>51 できるけど、コピー処理が重いから避けたいところだ。
53 :
デフォルトの名無しさん :02/08/16 16:56
あるクラスの派生クラスを作ったとします。 こんな関数を追加します。 xxx& operator << ( xxx ) { // 引数に何かの処理を加える // ここで基本クラスの他のストリーム演算子を呼び出すにはどうすればいいでしょうか? } this << xxxx こんな風にすればいいと思ったんですが無理でした。
基本クラス::operator<<(xxxx) はどうか
55 :
デフォルトの名無しさん :02/08/16 17:05
だれか GetPrivateProfileString 教えて頂けませんか?
57 :
デフォルトの名無しさん :02/08/16 17:08
>>54 ありがとうございます。コンパイル通りました。
>>51 vectorのコピーコンストラクタが例外を投げたら、処理自体が
成功してるのに返り値が失われるから、auto_ptrかboost::shared_ptr
に入れてから返すのが正解。
copy-on-writeですか?
vector::vector(....) と vector::vector(....) throw() の両方定義することができて、return のときはコピー先 オブジェクトの vector::vector() throw() が自動的に 呼び出されて欲しいっていうことなのかな。
>43 すみませんプロファイルとはどういう概念のものなのでしょうか? ひととおり調べたらVC6.0でプロファイルを取得する方法が出ておりましたが .NETの場合は良くわかりませんでした。
>>62 > すみませんプロファイルとはどういう概念のものなのでしょうか?
実際にプログラムを走らせて、関数や行単位で、実行時間・メモリ消費量などを
計測する。
問題の箇所を特定して、それから原因を潰そうってアプローチを採る場合に
有効な道具。
64 :
デフォルトの名無しさん :02/08/16 23:34
ごめん、出遅れた・・・・(TT)
>>61 いや、単に例外を投げないだけじゃなく、あたかもコピー元のデストラクタ
が呼ばれたかのように振舞う、ということ。auto_ptrと同じ発想。
実体をコピーするのはオブジェクト本体だけで、オブジェクトが参照して
いるポインタの向こうは、丸ごとコピーしないで、ポインタだけコピーする。
そうすれば、自然にthrow()にできるし、逆にコピー元は無効になってしまう
から、throw()でないと困る。
66 :
デフォルトの名無しさん :02/08/17 15:49
vector(vector &src, move_t) throw() : _M_start(src._M_start), _M_finish(src._M_finish), _M_end_of_strage(src._M_end_of_strage) {} で、これがコピーコンストラクタ部分でしょうか 厨な質問で悪いんですが…
>>66 そのつもり。変数名はSGI STLのマネ。
>>65 全てのクラスにmemcpy相当のコピーとゼロクリアを行う
フレンド関数を作っておけば良いんじゃない?
んで、stlの代わりも自分で書く。
つーかそうゆうの遊びで書いてみたことあるけど
確かにstlより相当はやくなるよ。
今のstringやコンテナの実装って大抵 copy-on-writeになっているだろ。 実体のコピーは使ってないよ。
>>69 string は copy-on-write が多いが vector で copy-on-write は珍しい気が。
っつか、あるのか?
71 :
デフォルトの名無しさん :02/08/18 02:49
Javaで言うClassクラスみたいなのってC++では無いのでしょうか… 検索エンジンでは探せませんでした。
ない
ぐは やっぱり無理ですか… どうもありがとうございます。
>>73 何に必要なのか分からんが、typeid()じゃダメかい?
#include <iostream>
// for typeid()
#include <typeinfo>
using namespace std;
int main(int argc, char **argv) {
Hoge tmp;
cout << typeid(tmp).name() << endl;
return 0; // EXIT_SUCCESS
}
ってやると、Hogeって表示されると思う。型名知るだけならこれで可能。
名前を知るくらいしかできないけどな
・゜・(ノД`)・゜・ウワアァアァアァァァン
リフレクション的な物は求めるべきではないだろう・・・。
78 :
Hikky! :02/08/19 00:21
for_each(-_-);
そのうち大学でもC++で宿題が出るようになるんだろうな。 それまで力がついているかな(((( ;゚Д゚))))ガクガクブルブル
海外じゃ当たり前っぽいけど。
>>79 うちjava〜。継承とかろくに教えず終了。いいのかそれで。。。
教養課程だったらそんなもんでしょ
>>82 専門です。情報科学部です。本当に良いのかそれで・・・。
>>83 javaなんかどうせ使うかわかりゃしないんだからやっても無駄。
必要になってからでも全然遅くないよ。つーかもっと理論を勉強なされ。
85 :
デフォルトの名無しさん :02/08/19 08:54
SDKとMFCどちらを勉強すればいいの?
その中からどちらか一方に絞りたいなら、SDKのほうだな。 最近は、もっといい選択肢があるだろうに・・・。
89 :
デフォルトの名無しさん :02/08/19 21:53
C++使いの先輩にお聞きします。 Q1 C++の悪いところって何ですか? Q2 C++の弱点って何ですか? Q3 それでもC++は最強ですか?その理由は?
>>89 Q1 度重なる改造手術で非常に不細工な言語仕様に
Q2 クラス多用するとサイズ増加、実行速度低下などを招く。まぁ、ほかのOOPLにも言えること。
Q3 デファクトスタンダード恐るべし。
>>90 クラス多用って一体……
非仮想関数であれば呼び出しは一般の (C 言語の) 関数と同等のペナルティだし、
仮想継承を使わなければメンバ変数へのアクセスも構造体に触るのと変わらん
よな。
>>91 いいよ, 自分で試した事ない奴はほっとけ. 非難するだけなら誰でもできる.
93 :
デフォルトの名無しさん :02/08/19 23:18
すみません、超初歩の質問だと思うのですが あるファイルの関数外でグローバルに宣言されているクラスを 別のファイルでも使えるようにするにはどうすれば良いでしょうか? 変数の場合、グローバル変数を別のファイルでexternと宣言すれば できると思うのですが、クラスの場合はどうすればよいのかわかりません。 良かったら教えてください。
>>93 クラスの宣言を Classname.h に、実装をClassname.cpp に書いて、
そのクラスを利用するファイルでは Classname.h を#includeする
っていうのが一般的だと思うが。
要は、クラス宣言が書かれていればよい。
宣言っていうのは
class Classname
{
public:
Classname();
...
};
って奴のことね。
.
すみません、どうも聞き方が悪かったようです。 言いたかったのは、あるファイルの中で使われているクラスの実体?を そのまま別のクラスで使う方法は無いかって言うことなんです。 ファイル間グローバル変数のように、あるファイルの中で変更された メンバ変数を別のファイルで参照できないかと思いまして。
C++使いの先輩にお聞きします。 Q1 C++の悪いところって何ですか? 文法に不自然な点が多い。 delegate がない。 Q2 C++の弱点って何ですか? コンパイルに時間が掛かる。 クラス定義が変わると、 全てのモデュールを再コンパイルする必要がある場合がある。 Q3 それでもC++は最強ですか?その理由は? プログラムの動作を厳密に制御できる。 実行時のオーバーヘッドが殆ど無い。
>>95 んーっと。
>そのまま別のクラスで使う方法は
>別のファイルで
別の(クラス|ファイル)どっち?
>>93 ああ、読み直してみるとなんとなくわかったかも。
グローバルなオブジェクトを使いたいってことですか?
それだったら普通の変数と同じく、どこか1カ所で変数宣言しといて
他のモジュールからは extern すればよい。
ただし、グローバルなオブジェクトはコンストラクタがいつ実行されるか
不透明なのであまりお薦めできない。
>>95 それオブジェクト指向(のカプセル化)の概念、完全に無視してるような…
とりあえず構造体にすれば…?
えっと、externで宣言しても 「そのオブジェクトは既に定義されています見たいなエラーが出て、 変数とは違うのかなって思ったんですが リビルドしたらできました(汗 >>97さん本当にありがとうございました。
こ の ス レ は C + + を 分 か っ た つ も り の
>>102 を 励 ま す ス レ に な り ま す た
あと使ったこと無いけどfriendとかもあるな goto並みにタブーなイメージだけど
まあ、goto程度にはタブーかも知れない。良くも悪くも。
107 :
デフォルトの名無しさん :02/08/20 15:46
標準ライブラリのendlとかhexみたいなものを自分で作るにはどうすればいいですか? 詳しく説明してるサイトとかないですか?探したんですけど見つからなくて・・・
>>107 単なる定数じゃないの、あれ?
と思ったら違ったわ。
VC7のファイルを検索
grep endl *.*
ostream.h:inline _CRTIMP ostream& __cdecl endl(ostream& _outs) { return _outs << '\n' << flush; }
109 :
デフォルトの名無しさん :02/08/20 16:04
>>108 うーん・・・なんかうまくいかないです。
もしかして、endlとかって何かのクラスのメンバ関数じゃないんですか?
111 :
デフォルトの名無しさん :02/08/20 16:09
エラーが出てコンパイルできませんでした。
未確認だけど ostream& ostream::operator<<(ostream& (*pfn)(ostream&)) { (*pfn)(*this); return *this; } こんな感じのメンバがあるんじゃないのかな。
113 :
デフォルトの名無しさん :02/08/20 16:15
ありました。 ありがとうございます。今からやってみます。
>110 <<flushの方は?
>>115 バッファに貯めとかないですぐに書き出せってことでしょ。
115は、「改行してるだけ」ではない、と言いたいのでは?
>>115 はflashの定義はどうなってんの?ってことでは?
おい喪前ら人に聞く前に自分でgrepしる! と思ったがそういうこと書いてる間に自分でgrep。 …ostream.h中にはなかったのでランタイムライブラリのソースコードを 引っ張り出してみた。VC7でつ。 ostream& ostream::flush() { lock(); lockbuf(); if (bp->sync()==EOF) state |= ios::failbit; unlockbuf(); unlock(); return(*this); }
>>108 Σ(´Д`;)
grepって正規表現でファイル指定できたのか・・・・
知らなかった師のう(-_-)
122 :
デフォルトの名無しさん :02/08/21 00:29
正規表現じゃないが
>>121 grep : global REGULAR EXPRESSION print
使えなきゃおかしいんだけどね。
でも、正規表現対応grepはegrepだったり。
謎。
>>120 今手元にC++環境無かったんだ。ごめんよ!
>>123 egrep は拡張正規表現対応ってことで。
Borland BCC55 basic_ostream<charT, traits>::flush() { if(this->rdbuf()) { #ifdef _RWSTD_MULTI_THREAD _RWSTDGuard guard(this->rdbuf()->buffer_mutex_); #endif if(this->rdbuf()->pubsync() == -1) this->setstate(ios_base::badbit); } return *this; }
調べてみた。 FreeBSD4.4,gcc2.95.3 ostream& ostream::flush() { if (_strbuf->sync()) set(ios::badbit); return *this; }
えぴすてーめーのチンコは大きいのですか?
>>129 あの人の名前が出てくるあたりがC++スレだな(w
>>131 うむ。BCCのが複雑になってるのはマルチスレッド時の排他制御を考慮
してるからだしな。それにしてもBCCのは見にくいが。
>>131 syncの中は排他制御でマクロだらけという罠
134 :
デフォルトの名無しさん :02/08/21 09:31
template で固定化された "" と L"" を使い分ける実験をしてるのですが、 下の使い方はあってますでしょうか? #include<string> template <typename T> void aa(const T *a) { std::basic_string<T> s = a; } class Data { char *m_ts; wchar_t *m_tsw; public: Data(){} Data(char* c,wchar_t* w) { m_ts = c; m_tsw= w; } ~Data(){} inline operator char* () const { return m_ts; } inline operator wchar_t* () const { return m_tsw; } }; int main() { Data data("1234567890",L"1234567890"); aa<wchar_t>((wchar_t*)data); aa<char>((char*)data); }
なにか問題があるのか?
>>134 aa<wchar_t>(data);
aa<char>(data);
の方が好ましいかと。
{ Data data("1234567890",L"1234567890"); aa<wchar_t>((wchar_t*)data); aa<char>((char*)data); } 同じブロックスコープ内で 上記の文字列"1234567890"のポインタを参照した場合、 その実体がまだ存在していることは保証されているのでしょうか?
はい?
{ char ts[] = "1234567890"; wchar_t tsw[] = L"1234567890"; Data data(ts,tsw); aa<wchar_t>(data); aa<char>(data); } 137のようでなく、このように書くべきなのでしょうか。
>>139 貴様、もしかしてそれは、要するに、
const char* aa() { return "1234567890"; }
const char* bb() { char ts[] = "1234567890"; return ts; }
での戻り値は有効か、とかいう話ではないですか?
template も C++ も関係ないような・・・。
文字配列のインスタンスはスコープで死ぬが、文字列リテラルはstatic。
↑の bb がダメで aa は大丈夫。
142 :
デフォルトの名無しさん :02/08/22 01:41
Borland C++ Compiler で Windows プログラミングを はじめたいのですが、解説してあるサイトがなかなか見つかりません。 よいサイトがありましたら教えてください。
146 :
デフォルトの名無しさん :02/08/22 08:46
147 :
デフォルトの名無しさん :02/08/22 11:01
>>144 猫でも分かるは VC++ を使っているようなのですが
もしかしたらコンパイルできるのかもしれないと思って
bcc32 -tW sample01.cpp
としたのですが
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
win1.cpp:
エラー E2034 win1.cpp 22: 'void *' 型は 'HBRUSH__ *' 型に変換できない(関数 __stdcall WinMain(HINSTANCE__ *,HINSTANCE__ *,char *,int) )
警告 W8057 win1.cpp 46: パラメータ 'lpszCmdLine' は一度も使用されない(関数 __stdcall WinMain(HINSTANCE__ *,HINSTANCE__ *,char *,int) )
*** 1 errors in Compile ***
というエラーがでてコンパイルできませんでした。
22 行目をコメントアウトしたらコンパイル実行できましたけど、これから学習するに当たって
これは無視していい程度のことなんですか。
OS が Win98SE だからこんなエラーが出るんでしょうか。( 2000とかだと出ない?)
>>147 もうちょっと低いレベルで学習すべきではないかと。
>>147 (HBRUSH) GetStockObject(〜);
もしくは
reinterpret_cast<HBRUSH>(GetStockObject(〜));
または、sample01.cでコンパイル
>>149 キャストすればよかったんですね。
というわけで「猫でも分かる」でも勉強できそうなので、
ここでしばらく頑張ってみようと思います。ありがとうございました。
>>154 >サイトがハッキングされたのか
これ以上しゃべんなよ。頼むから。
いやでも実際バグってるんですが。
>実際バグってるんですが。 /・ 。・\ <まぁ、いいんだけどね。)
>>156 Mozillaだとだめぽ。IEでもダメなの?
つーかMozilla使ってそうには思えないがナー(w
>>149 なぜreinterpret?
static_castじゃいけない理由を教えてください^^;
>>159 static_cast にすべきですよね。失礼しました。
いつも reinterpret_cast<HBRUSH>(COLOR_WINDOW+1);
とやってたのでその勢いで書いてしまった・・。
>>162 > static_cast にすべきですよね。
この場合は、別に reinterpret_cast でも良いと思うが。
164 :
デフォルトの名無しさん :02/08/22 22:40
ifの実装ってどのファイルに書いてあるんですか?
>>164 gcc なら gcc/c-parse.y かなぁ?
167 :
デフォルトの名無しさん :02/08/22 22:50
VCなら?
>>167 マイクロソフトに聞け!
# 「聞け!」を2ch語にできないかなあ「する」→「しる」みたく。
マイクロソフトに聞き! …うーん
169 :
デフォルトの名無しさん :02/08/22 23:10
マイクロソフトに菊!
170 :
デフォルトの名無しさん :02/08/22 23:10
マイクロソフトに菊座!
>>168 しる!は形が似てるから間違えたんでしょ、ってことで
聞は!
はどうですか?
reinterpret_castは整数型とポインタ型との相互変換に使う、とあるよ。 最も低レベルだから気軽に使うなと…((((゚д゚))))ガクガクブルブル int n = 12345; int *p = &n; int n_addr = reinterpret_cast<int>(p); // n_addrにはpのアドレスが整数値として入る
マイクロソフトに効く!
マイクロソフトに奇形
>>168 っていうか
×「する」→「しる」
○「しろ」→「しる」
2典でも読んでくだちいってことで。
マイクロソフトに悶け!
>>172 ポインタ同士の変換もreinterpret_castでしょ
179 :
デフォルトの名無しさん :02/08/23 02:09
マルチスレッドでの例外処理なんですが。 サブスレッドで発生した例外を、メインスレッドに上手く伝播させる方法ってありますか?
なんでC++ってキャストの仕方がたくさんあるんだよ。 無理な拡張ばっかりしてるからそんなことになるんだよ。
>>180 GCがなくてポインタが使えてデフォルトで無効なキャストが出来てしまうせい。
184 :
デフォルトの名無しさん :02/08/23 04:17
>>183 おい。勝手にネタにすんなよ。
C++だけだろこんなにキャストの仕方があって
いちいちプログラマが使い分けなきゃならんの。
こ の ス レ は C++ を 使 い こ な せ て い な い
>>184 を 暖 か く 叩 く ス レ に な り ま す た
C++にいろんなキャストがあるってのは ( Hoge ) hoge; Hoge ( hoge ); reinterpret_cast< Hoge >( hoge ); という形式の話なのか、それともC++スタイルの4種のキャストの話なのか。 それとも全部ひっくるめての話なのか。 boostあたりの偽キャストtemlateあたりになるとさすがにどうかとは思うが。 紛らわしい。
嫌ならCスタイルのキャスト使えば? それかreinterpretだけ使ってればいいじゃん。
static_castだの何だのの話しは前スレで既出じゃなかったか?
>>187 全部の話だ。ある型から他の型に変えるときそこで使用されるキャストすべてだ。
だいたいキャストごときでテンプレート使っているのが気に食わん。
>>188 自分一人で勝手に作れるのならそうする。
もっとも勝手にやれるならキャストを使い分ける方を選ぶがな。
>>186 前にも解説したような覚えがあるんだが。とりあえず前スレ読んでみ?
>>191 キャストの違いなら一応わかっているつもり。
俺が知りたいのは何故こんなにキャストの仕方があるかという理由だ。
C++形式のキャストにはそれぞれ明確な用途がある。 C形式のキャストが残ってるのは単なる過去の負の遺産。
確かにCのキャストなんか使ってないね。
C style castは人間が間違えたときに悲惨だから 意図を明示した複数の長いキャスト指令に分割することで 意図以外のキャストをしてしまうミスを減らすものでんな。 また、C style castは危険なのだがソース中で埋もれてしまうので、 reinterpret_castという同等の固有指令を作って危険な文を発見しやすくしたって感じ? どうせなら移行促進のためにC style castに警告ぐらい出してくれればいいのにな。
C++キャスト厨が湧いてるようだな
_________ /∴∵∴ヽ |∵∴∞ヽ| _______________ |∴/= ♀=| <dynamic_cast以外使ったことねー! \| ▽/  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄  ̄ ̄
C爺はCスレ池。voke
>>192 違いが分かっていれば、理由は明白なはずだが……。実は「分かってるつもり」
なだけ?
とりあえず C スタイルキャストと static_cast, dynamic_cast, reinterpret_cast の
違いについて書いてみ。
>>197 お前は Win32 プログラミングをやったことがないのかと…。lParam, wParam を
キャストするときに dynamic_cast はあり得んだろ。
>>199 たぶん新しい(新しくもないが)形のキャストの話でしょ
>>192 199の設問だと意図が掴みにくいだろうから、もっと端的に。
「ポインタ同士の変換でstatic_castとreinterpret_castがどう異なるか説明せよ。」
だいたいお前ら!危険だの危険でないのと騒いでいるが キャストがバグの原因だったことあるか?俺はない
取りあえず放置で。
Cを使っていたときは暗黙のキャストでたまにバグったが それもC++になって型変換が厳しくなってからはそれもない。 (その代わりにコンパイラがエラーをげろげろはく) 明示的キャストではCでもバグったことはない。 C++でキャストが沢山あるのは主にその機能の必要性からであって (バグ対策の)開発支援のためではないだろう。 そしてそれぞれの機能のキャストを選択的に使えなければならない。 これがC形式のキャストでは出来ないことだ。もう一度言おう、 危険かどうかが問題なのではない。機能の違いが問題なのだ。 私は主に(ポインタではない)値のキャストにC形式を用い、 (これは式の記述の簡便さにもよるし曖昧さがないことにもよる) OOに関するものにC++の長ったらしいキャストを用いている。 その必要があるからだ。 (static_castとreinterpret_castでさえ保証されている内容は全く違う。 Cタイプのキャストではどちらが適用されるか一見して分かるわけではない) ご静聴ありがとう
多重継承やら仮想関数のあるクラスポインターをキャストする時に問題になる話しだな。 virtualキーワード使わなければさほど意識する必要はないでしょ。 int を enum へ キャストする時 static_cast は重宝した。
Cスタイルキャストって、文脈によって static_cast か reinterpret_cast かに切り換わるの?
>>207 規格では
const_cast
static_cast
const_cast+static_cast
reinterpret_cast
const_cast+reinterpret_cast
のどれかが適用されることになっている
おお、そんな風になっていましたか。
ありがとうございました。
>>208
だれか
>>201 の言っている
>「ポインタ同士の変換でstatic_castとreinterpret_castがどう異なるか説明せよ。」
について説明してくれ・・・・dynamic_castとCスタイルのキャスト以外知らないので気になる・・・・
>>210 激しく同意。
解説しる!……いや、してください…。
キャストの話って度々でるな
>>210 多重継承してるときに、オフセットの調整するかどうかじゃないの?
class B1 { int b1; };
class B2 { int b2; };
class D : public B1, public B2 {};
D* pd = new D;
B2* pb = bd;
こうすると pd と pb は、それぞれ「D オブジェクトの先頭 (= B1 オブジェクトの先頭)」
「D オブジェクト中にある B2 オブジェクトの先頭」を指すよね。
pd-> +------------
| int b1;
pb-> +------------
| int b2;
+------------
当然、アドレス値としては pd != pb になる。このときに
1. static_cast<D*>(pb) するとオフセット分だけ差し引いて pd と同じアドレスが返ってくる
2. reinterpret_cast<D*>(pb) すると pb のアドレスが、そのまま返ってくる
(規格上は実装依存だけど、たいていの処理系だとこうなる)
と、結果が違ってくる。
>>210 reinterpret_cast がビットパターンを変化させずに型変換するのに対して
static_cast はそのポインタ型にとって適切なビットパターンに変換してくれる
ということではないのかな。
>>213 あれ?ってことは
>reinterpret_cast<D*>(pb)
って危険なんじゃ?
D*の型として取り出せるけど,じつは正しくアクセスできない?
>>216 派生型への変換を目的としているならそれは正しくない使い方
static_castを使う。ちょっと違う部分(ほとんど全て)を適当に訳してみた
reinterpret_cast
・他の型への変換における値の互換性は実装依存。
・ポインタ型は十分なサイズの整数型に変換できる。
・整数型と列挙形はポインタ型に変換でき、ポインタ型から変換された整数は
同じポインタ型への変換によって正しくもとのポインタに戻る。
・関数ポインタを他の型の関数ポインタに変換できる。
それを使った呼び出し結果は未定義。ある型への変換の後もとの型への変換によって
正しくもとの値に戻る。それ以外の動作は不定。
・オブジェクトへのポインタを他の型のオブジェクトへのポインタに変換できる。
その動作は上と同様。
・メンバオブジェクト、メンバ関数それぞれのポインタを
他のオブジェクトの他の型のメンバポインタに変換できる。動作は上と同様
・ある型のポインタから他の型のポインタへのreinterpret_castを適用できるときに限り、
その型の左辺値を他の型の参照に変換できる。一切の一時オブジェクトの生成、コピーの生成
コンストラクタや変換関数の呼び出しは行われない。
static_cast
・ある値を他の型の変換コンストラクタが適用できるときに限りその値に変換できる。
・任意の値をvoid型に変換できる。その結果、式は値を放棄する。
・派生型のポインタから基底型のポインタに変換する標準変換があるときに限り、
基底型の左辺値を派生型の参照に変換できる。基底は仮想基底であってはならない。
値が派生型の部分値(要はアップキャスト)でないときに動作は未定義。
・各種標準変換の逆変換ができる
・整数型を列挙型に変換できる
・標準変換が存在するときに限り基底型のポインタを派生型のポインタに変換できる。
基底型は仮想基底であってはならない。動作は参照のときと同様。
・基底型にあるメンバがあり、基底型のメンバポインタから派生型のメンバポインタへの
標準変換があるときに限り、派生型のメンバポインタを基底型のメンバポインタに変換できる。
・オブジェクト型のポインタとvoid型のポインタの相互変換ができる。
もとのオブジェクト型への変換により正しくもとの値に戻る
あと、C形式のキャストでは const_cast static_cast const_cast+static_cast reinterpret_cast const_cast+reinterpret_cast が順に適用されるのに加えて、 公開されていない基底に正しくキャストすることができる。 これはreinterpret_castにもない機能 (static_castではそもそも不可能)
(続き)もちろん派生側にもキャストできる。 reinterpret_castはポインタをほかの型に変換してもどす以外には 役立たずで不必要に見えるが、ほかの型に変換した結果が 不定(未定義ではない!!)というのがみそでwindowsの例だけども BITMAPINFO bmpi ; reinterpret_cast<BITMAPINFOHEADER*>(&bmpi) ; のような記述を許容している。互換性のためには必要なわけだ。 static_castを二回(一回void*にする)使えばできるかもしれないが 規格に全く書かれていないstatic_castの使い方になってしまう。
∩ | | | | ∧_∧ | | / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ( ´Д`)// < 先生!わざわざ訳してくれてありがとうございmす! / / \ / /| /  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ __| | .| | \  ̄ ̄ ̄ ̄ ̄ ̄ ̄\ ||\ \ ||\|| ̄ ̄ ̄ ̄ ̄ ̄ ̄|| ̄ || || ̄ ̄ ̄ ̄ ̄ ̄ ̄|| .|| ||
222 :
デフォルトの名無しさん :02/08/24 17:06
stringstreamで文字列に戻したときに floatの文字列になっているみたいなのですが、 doubleの文字列にするにはどうしたらいいのでしょうか? #include <iostream> #include <sstream> #include <string> using namespace std; int main() { stringstream oss; string mystr; double d = 1234.567890; oss << d; mystr=oss.str(); cout << mystr; //1234.57 return 0; }
setprecision
>>223 thanks
<< double するときは setprecisionが必要なのか...。
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
using namespace std;
int main()
{
stringstream oss;
string mystr;
double d = 1234.567890123456,d2;
oss << setprecision(16) << d;
mystr=oss.str();
cout << mystr << endl;
oss << mystr.c_str();
oss >> d2;
cout << setprecision(16) << d2 << endl;
return 0;
}
浮動小数点のデフォルトの出力精度が6桁までなので。
226 :
デフォルトの名無しさん :02/08/25 00:10
質問です。 あまり C++ とは、関係のない話題なので申し訳ないのですが、 bcc5.5.1 で Windows DLL の作成・利用の仕方についての質問です。 以下のソースで試しているのですがどうにもうまくいきません。 DLL の作成には成功するのですが、DLL から関数のポインタを取得 するのに失敗してします。 宜しければ、間違いがどこにあるかご指摘いただけないでしょうか? または、参考になる URL でも構いません。 bcc32 -O2 -WD testdll.cpp // DLL 作成時のコンパイラオプション bcc32 -O2 test.cpp // EXE 作成時のコンパイラオプション -- testdll.h -- int __declspec(dllexport) __stdcall MyFunction(int); -- testdll.cpp -- #include "testdll.h" int __stdcall MyFunction(int x) { return x+100; } -- test.cpp -- #include <windows.h> #include <cstdio> using namespace std; typedef int (*TFUNC)(int); int main() { HINSTANCE hInstDLL; TFUNC DllFunction; if((hInstDLL=LoadLibrary("testdll.dll"))==NULL) { std::printf("オープン失敗"); exit(1); } if (DllFunction=(TFUNC)GetProcAddress(hInstDLL,"MyFunction")) std::printf("%d\n\n",DllFunction(1)); else std::printf("しっぱい\n"); if(!FreeLibrary(hInstDLL)) { std::printf("クローズ失敗"); exit(1); } return 0; } -- 実行結果 -- C:\SLLTEST>test しっぱい よろしくお願い致します。
> あまり C++ とは、関係のない話題なので申し訳ないのですが、 それを知っててなんでこのスレに書くんだよ。extern "C"
228 :
デフォルトの名無しさん :02/08/25 00:24
#defineについて質問です。 class Aに Allocate(a,b)という関数があり class Bには Allocate(a) という関数があります。 class AのAllocate(a,b)を置換したくて #define Allocate(a,b) AllocateEx(a,b,__FILE__,__LINE__) とすると、class Bの Allocate(a)まで対象となってしまい しかも引数の数が合わないとコンパイラに怒られます。 なんとかclass AのAllocateだけを置換対象とする事はできないでしょうか? それとも別の解があれば、教えてください。
>>229 同意。マクロなんて、どこで影響出るか分からんから使うな。
いちおう回避策はあって、たとえ Allocate という引数付きマクロが定義されて
いたとしても (Allocate) と書くとマクロ展開を抑制できる。
>>228 inline使え、って言ってもらいたいんだろ?
>227 失礼致しました。 もう少し勉強してきます。
233 :
デフォルトの名無しさん :02/08/25 00:52
>>231 inline使うと、どうなるんですか?
置換対象のソースが膨大で、できればマクロで済ませたいのです。
>>233 Allocateは関数なんだろ?
だったらその内部でAllocateExを呼べばイーんじゃねーの?
>>235 __FILE__ とか __LINE__ とか書いてあるところから察するに、デバッグビルド用に
切り分けたいんじゃないかと。
>>236 マクロに不都合があるなら、関数内部でデバッグルーチン組んでもいいかと思う。
Bの前で#undef
B(愛撫)の前はA(キス)。 ちゃんと覚えとけ。
>>239 なんでBが愛撫でAがキスなんですか? Cはセックスですか?
無名クラスにコンストラクタを定義する方法ない?
243 :
デフォルトの名無しさん :02/08/25 08:13
みんなキャストに夢中で
>>180 に答えてくれない。デョボーン(|||ω・`)
違った
>>179 だった。デョボーン(|||ω・`)
>>244 二度とバカなこと言わんようにな。と言うところ。
つーか、まっとうな方法なら、サブからメインにメッセージ 渡すしかねーだろ。ウインドウメッセージとかさ、メインスレッドが サブスレッドの例外状況をポーリングするとかさ。
今、たった今、VC++でハロワルできました。 記念すべき最初のプログラムでした。 これからよろしくお願いします。
>>248 >ハロワルできました。
通ぶるなら来るなよ。
>>249 さんごめんなさい。
また来させてください。
>>251 健全なスキルアップは健全な用語からだ。ってことじゃないの?
>>253 メンバ関数でいいような気が。
なぜコンストラクタじゃないと駄目なの?
唯一のオブジェクトを記述するのに クラス指向でないオブジェクト指向でエレガントに記述してみたかっただけ C++では機能が少なすぎるな
pragmaってどういう意味?使い方じゃなくて、英単語として。名前の由来というか。
>>255 new、delete オーバーロードして自前で関数を呼び出すとか。
と思ったけど名前が無いから無理か・・・。
260 :
デフォルトの名無しさん :02/08/26 13:42
>>37 >>98 上に関連して教えて下さい.
コンパイル単位が複数あるときに,あるコンパイル単位中のグローバルオブジェクト
やグローバル変数を一番最初に初期化する方法ってありますか?main()関数内でこれ
らを初期化する関数を最初に呼び出せば良いでしょうけど,できればこの関数の呼び
出しをmain()関数内で明示的に呼び出すのではなく,裏側でこそっと呼び出したいの
ですが.
261 :
デフォルトの名無しさん :02/08/26 13:50
>>260 グローバルオブジェクトを初期化する関数をmain()関数内で最初に呼べばok
かどうかも妖しくなってきた.
263 :
デフォルトの名無しさん :02/08/26 15:33
>>262 どうもです.
realmainの補足説明をもう少しいただければありがたいのですが.
〜を調べろとか,〜のサイトを見ろとか.
>>263 int realmain()
{
/* main のかわり */
return 0;
}
int main()
{
初期化();
return realmain();
}
265 :
デフォルトの名無しさん :02/08/26 16:12
シャブ中の1が何言っても無駄
266 :
デフォルトの名無しさん :02/08/26 16:16
質問です。 int *a; と int* a; って何が違うんでしょうか?
>>266 書き方が違う。
int * a;って書くやつもいる。
268 :
デフォルトの名無しさん :02/08/26 16:19
>>264 ありがとうございます.コードをじっと見てるうちにその意味が
少しだけわかってきました.勉強させてもらいます.
269 :
デフォルトの名無しさん :02/08/26 16:21
>>267 書き方だけの違いだったのか。
了解しました。
271 :
デフォルトの名無しさん :02/08/26 16:24
Rubbj mkl,,......CCCC*********++
>>269 オブジェクト指向な俺は
インテジャーポインタという型だと主張したいから
int* a;と書く方針。
他人には強制しないがint *a;派のやつからはいろいろ文句言われる。
>>272 ポインタ型として宣言するか、
宣言したものがポインタであるのか。
結局同じ事なのか・・・
もう一つ質問です。
int* a;がなんでオブジェクト指向なんすか?
>>273 >int* a;がなんでオブジェクト指向なんすか?
それ自体はオブジェクト指向でもなんでもないけど、
ポインタなんていう概念をできるだけ隠蔽したいという意志の現れだから。
質問お願いします。 以下のように、一時変数をリストに挿入した場合、スコープを抜けた後も、 リストに挿入したtemp_msのデータは保持されるのでしょうか? list<MyStruct> list_ms; func(){ MyStruct temp_ms; list_ms.push_back( temp_ms ); } main(){ func(); }
値を保存しているのだから当然格納されたオブジェクトは コンテナと同じ寿命を持ちえる
277 :
デフォルトの名無しさん :02/08/26 17:43
<<276 本当? push_back関数が値コピーして要素追加するならいいが void push_back(const T& x)となってる. ローカルオブジェクトは関数から抜けると破棄されるから危ないのでは?
278 :
デフォルトの名無しさん :02/08/26 17:47
えいくそっ! <<276 じゃなくて
>>276 だった.
list<MyStruct&>ならばね。しかし 参照型のコンテナはそもそも許されないはず
>>277 >本当? push_back関数が値コピーして要素追加するならいいが
>void push_back(const T& x)となってる.
TがMyStructでMyStruct temp_msとあるから
listのスコープが終わればその要素も破棄されるよ。
ただしMyStructのデストラクタをちゃんと書いてなければ
MyStruct内で定義されたデータは破棄されないことに注意。
>ローカルオブジェクトは関数から抜けると破棄されるから危ないのでは
この文章をみると知識だけあって理解してない厨房に見えるけど。
C++ での DLL 作成に関して質問をした者です。 >227 様のヒントのおかげでどうにか解決できました! ありがとうございました。 おかげでバックグラウンドの重めの処理を C++ で作成、 GUI は別の言語で 作りこむっていうステキなことが出来るようになりました。 原因 以前のが上手くいかなかったのは、C++だとなにやら「マングル」という卑猥な単語 が激しく関係する為だったようです。 回避策 関数郡を extern "C" してあげればそれが回避できるようです。 bcc32 -O2 -WD dll.cpp // DLL 作成時のコンパイラオプション bcc32 -O2 test.cpp // EXE 作成時のコンパイラオプション -- dll.h -- #ifndef __DLL_H__ # define __DLL_H__ #include <windows.h> #ifdef __cplusplus extern "C" { #endif __declspec(dllexport) int __stdcall MyFunction(int); #ifdef __cplusplus } // extern "C" #endif #endif // __DLL_H__ -- dll.cpp -- #define __MAKE_DLL__ #include "dll.h" namespace mydll{ __PORT int __stdcall MyFunction(int x) { return x+100; } } -- test.cpp -- #include <windows.h> #include <cstdio> using namespace std; typedef int __stdcall (*TFUNC)(int); int main() { HINSTANCE hInstDLL; TFUNC DllFunction; if((hInstDLL=LoadLibrary("dll.dll"))==NULL) { printf("オープン失敗"); exit(1); } if (DllFunction=(TFUNC)GetProcAddress(hInstDLL,"MyFunction")) printf("%d\n\n",DllFunction(1)); else printf("しっぱい\n"); if(!FreeLibrary(hInstDLL)) { printf("クローズ失敗"); exit(1); } return 0; } -- 実行結果 -- C:\SLLTEST>test 101 ありがとうございました。
前スレで1000とったのは俺だよ…エヘヘ… 俺って天才だよな。
>>282 ああおまえは天才だ。とおだてたところで一発ネタかましてください。
>281 dll.cpp にいらぬものが入ってました。 訂正。 -- dll.cpp -- #include "dll.h" __declspec(dllexport) int __stdcall MyFunction(int x) { return x+100; } 板汚し、すんまそん。
285 :
デフォルトの名無しさん :02/08/26 19:48
>>277 勘違い! void push_back(const T& x)は値コピーで要素追加だった.
コピーコンストラクタの引数も const T& x だし.
>この文章をみると知識だけあって理解してない厨房に見えるけど。
ああ永遠の厨房よ.
>const T& C++3rdの135頁に詳しくかいてある
>>277 =
>>285 自己修正してるらしいけど・・・・
そっとしておいてやるべきか、いやはっきり逝ってやるのがいい。
(・∀・)カエレ
>>276-280 >>285 お礼が遅くなってすいません。今まで下さったレスの意味を
必死で考えていました。
listが内部で自動的にnew、deleteか何かをしてくれていて、
リスト追加は、ポインタ(参照)リストとかでない限り、値コピーで渡される。
clear()した場合はデストラクタが呼ばれる。…ということですよね
まだC++始めたばかりで、本当に助かりました。
レス有り難うございました。
294 :
デフォルトの名無しさん :02/08/26 22:30
質問です。 class Test { public: Test(void) { cout << "コンストラクタ" << endl; } void operator () (void) { cout << "オペレーター" << endl; } }; というクラスがありまして、 Test a; とやるとコンストラクタが呼ばれるんですが、 Test a(); とやると、コンストラクタが呼ばれないんですが、 これは仕様ですかね?それとも違う(隠れた?)コンストラクタ呼んでるんですかね?
Test a(); ってTestを返す関数aの宣言では?
>>295 なるほど!!
スコープ内でも宣言ができるとはしらなんだ。
どうもありがとうございました。
まあ罠といってもいいでしょうね。 C++ では、「宣言とみなせるところは宣言と解釈する」というのが ルールのようですから。
>>260 一般には、ない。ただし処理系によってはリンカのオプションで指定できる
ケースもある。
良く使う workaround は「ローカル static オブジェクト」を使うことだね。こんな
感じ。
CFoo& GetGlobalCFoo() {
static CFoo foo;
return foo;
}
#define g_foo GetGlobalCFoo()
ローカル static オブジェクトに関しては、最初に参照されたタイミングで
初期化されることが決まってるから。
300 :
デフォルトの名無しさん :02/08/27 00:41
コールバック関数ってどういうときに便利なんですか? Windowsのコールバックでなくて、もっと一般的な意味で コールバックを使った簡単なコードを誰か貼り付けてもらえませんか? ちなみに私はコールバックを使ったことが一度もありませんが、 特に困ったことはありませんでした(多分)。
>>300 C++ だと関数オブジェクトや仮想関数が使えるからな…。
素の C だと、たとえば qsort() で比較に用いる関数を指定するのに使ったり
するわな。
303 :
デフォルトの名無しさん :02/08/27 02:05
漏れの持ってる本には、メンバー関数定義するとき、 常にvirtual宣言せよって書いてあるんだけど、実際そうなんですか?
>>303 読み間違いでは?
本の名前と原文をうpしてくださいw
本の名前は、 「憂鬱なプログラマのためのオブジェクト指向開発講座」 Tucker!著 です。 その本の151ページに、 「メンバ関数はどれも将来オーバーライドされる可能性があり・・・(中略) メンバ関数は基本的にすべて仮想関数として実装しておいたほうがいいでしょう」 と書いてあったのです。
>>300 DLLを作ったことがない人にはわかりません。
309 :
デフォルトの名無しさん :02/08/27 02:20
>>303 常にってのはちょっと、、、、
>>300 コールバック(というより関数ポインタ?)使うのは
関数ポインタでテーブル作ってswitchの代用にしたり、
STLとかの関数オブジェクトにしたり、
あとはUIの応答のときとか
シグナルや入出力を待つときとかに使うくらい、
>>305 一理あるけど、
他人や将来の自分にオーバーライドしてほしくない関数は基本的に仮想関数にしないよね。
>>306 逆に言うと、DLLを作らないならコールバックはまったく使わなくて
いいということでしょうか?
>>311 あなたがコールバックを使うレベルになるまで、使う必要はありません。
>>310 多くの場合は、仮想関数にしておいて、
特別な関数は、仮想関数にしないという事でしょうか?
だとすると、特別な関数ってどんなのか知りたいです。
300には将来に渡って、コールバックは必要ないでしょう。
>>313 特別っていうかfinalにしたい関数は仮想にしないよね。
再利用の可能性がまったくない、他人に弄ってもらっては困る関数など。
ってゆうかDLLのみでソースがないときに
オーバーライドしたいけどできねーってことがないようにvirtualにしておくことはおすすめだけど、
、
そういう用途でなければ通常は後からvirtualキーワードを書き足せばいいわけで。
まあ実用的なプログラムつくるようになればわかるよ。
>>316 ご丁寧にありがとうございます。
ちょっと理解しますた。
>>310 > 他人や将来の自分にオーバーライドしてほしくない関数は基本的に仮想関数にしないよね。
まぁ、あの本は OO の入門書だから。
>>313 OO 分析の過程で出てきたメソッドではないもの。
例えば Generic Programming の流儀から出てくる operator() とか、実装の都合で
「処理が長くなるから関数に分けるか」ってな感じで作った private メソッドなど。
個人的には、実装の都合で出てきたメソッドに関しては pimpl イディオム使って
隠蔽した方が良いと思うけど。
>>319 今の漏れの実力じゃ、理解できないです。
もうちっと勉強してから出直してくるよ。
どうも、ありがとうございます。
>>320 ちと言葉足らずだったね。
C++ ってパラダイムごった煮の言語で、「憂鬱本」が解説してるような OO 流儀で
書くことも出来れば、STL のような Generic Programming 流儀で書くこともできる。
伝統的な C 言語のように、データ抽象 + 手続き指向も可という懐が広い言語。
OO 流儀でプログラミングする場合には
1 まず問題を OO で分析して
2 それを元に OO でクラス階層を設計して
3 最後に実装する
という手順を踏むから、必然的に 2 で出てくるクラスのメソッドは、原則として
virtual になる。
ただ純粋な OO 以外の設計・分析も入ってくると、必ずしも継承前提のクラス
ばかりではなくなるから(継承しない以上)virtual も不要になる。たとえば STL
コンテナは Generic Programming という OO とは別の流儀を採用してるから、
メソッドは全て non virtual だよね。
とりあえず「憂鬱本」は OO の入門書で、OO で分析・設計した成果をコードに
落とす道具として C++ を使っている。ただ C++ では他の流儀も使えるよ、って
ことだけ頭の隅に置いておけば良い。
(憂鬱本を読み終えたら、次に CODE COMPLETE とか Generic Programming
とか読んでみると良いかも)
>>319 親切なレスにめちゃくちゃ感謝してます。
まずは、ありがとうございます。
最近まで、はじめてのC++的な本で勉強していて、一通り理解したので、
他のスレで紹介されていた憂鬱本を読み始めたんです。
UMLとか全く知らなかった自分にとって、この本に書いてある事は
かなり衝撃的で面白く読めました。
是非、次は教えて頂いた本を読んでみようと思います。
基本的にvirtualになんてのは古い考えだね。 virtualは情報隠蔽の原則を破壊する、この欠点は大きいということが 最近になって強く認識され出した。 JavaでデフォルトがvirtualになったがC#の時代になると、デフォルトが finalに戻った。
325 :
デフォルトの名無しさん :02/08/27 09:28
326 :
勉強中@C++ ◆lawMy/JQ :02/08/27 13:15
こんにちは。スレ名につられて、別のスレに書き込んだのですが、どうやらそこはネタスレ だったようです。鬱 マルチポストになって申し訳ありませんが、改めてここで質問させてください。 以下コピペ >はじめまして。オブジェクト指向を勉強中のものです。 >最近、ミックスインクラスとロールプレイングクラスの存在を知りました。 >私は複数(かなり多い)の問屋を相手にするオンラインシステムを開発・メンテしている >のですが、問屋毎にいわゆる「特別処理」が多く、手を焼いています。 >そこで、ロールプレイングクラスを使うとこの「特別処理」をすっきり実装できるのでは? >と考えているのですが、似たような案件を扱った方がいらっしゃれば、ご意見をお聞かせ >いただけませんでしょうか?よろしくお願いいたします。
327 :
デフォルトの名無しさん :02/08/27 13:30
>>324 先生、何故virtualが情報隠蔽を壊すのでしょうか?
継承が壊すというのは分かります。
328 :
デフォルトの名無しさん :02/08/27 13:53
char型のデータを数値として出力したいんですけど cout ではどうするんでしたっけ? C だとこんな感じのやつ printf("%d", ch); // ch はchar型
intにキャストすれば?
cout << dec << ch << endl; だったけな?
>>327 まぁ、厳密にはそうだね。virtualだと継承した時に内部の実装を
知る必要が出てくる事が多いし壊しやすいと言うこと。
static_cast<int>(ch) int(ch)
int(ch) これってint型の一時オブジェクトを生成して左辺に代入ってことですか?
>>333 左辺ないだろうに。intでキャストしているだけ。
>>333 ISO+IEC+14882-1998.pdf
とか見れ。
C言語初心者ですが、 LSI C-86 v3.30c試食版を使ってコンパイルしようと思うのですが、 書いてあるとおりやってからプロンプトで「lcc ****.c」 と入力すると、 「lccは操作可能な・・・ではありません」とか出てきてしまって、コンパイルできません。 一体どうしたらできるようになれるのでしょうか。。。
VC6.0 スタンダードでも ProcessorPackを入れると最適化できるようになるって 本当ですか?
>>336 パス通した?
っていうかLSI-CよりBCCを使えと(略)
Cygwinいれてgccという手もある。 unix系を扱ったことがあるなら、こっちもおすすめ
VC6.0のメンバーテンプレートの問題って、 メソッドテンプレートだけじゃなかったんだね。 template<class T> class Outer { class Inner_ { T t; private: Inner(const T& ref) : t(ref) { } } Inner; public: Outer(const T& ref) : Inner(ref) { } }; これが通らなくて鬱ですた。
>>331 > virtualだと継承した時に内部の実装を知る必要が出てくる事が多いし
それは仮想関数ではなく、実装継承のデメリットを語ってるように聞こえるが…。
インターフェース継承も実装継承もvirtualキーワードしか関係しないからねえ...
>>331 それは、親クラスがいい加減な実装をしているか、
子クラスの実装が親クラスの仕様を無視しているだけ。
>>347 継承によるコード再利用は諸刃の剣。素人にはおすすめできない。
>>350 めいっぱい易しく書いたつもりなんだが。
とりあえず「実装継承」と「インターフェース継承」で google 逝ってくれ。
353 :
デフォルトの名無しさん :02/08/28 03:33
バカらしい質問で申し訳ないのですが。 様々な変数を宣言します。 int iText; BOOL bText; char cText; さて、TCHAR型なら なんという変数名ならみなさん見やすいですか?
あんたの命名規約意味不明なんでなんとも。
>354 えっもしかして、現時点で私狂ってます?
>>355 人に聞かなくても自分を客観的にみれるようになれば一人前だよ。
>>353 bool型のテキストってなんかいやん。
bool型、int型でTextとだけ付ける事自体間違ってる。
つかTextってどういう意味が?
文字ならばtextよりもcを使うかな。TCHAR,char,wchar_tに依らず。
すみません、 bTest のつもりでした。 間違えてテキスト、とタイプしていたようです。 申し訳ない。 tTest ということでよろしいでしょうか?
>>353 型情報を変数名に付加しなければいけないほど
プログラムが汚いってことですか?
364 :
デフォルトの名無しさん :02/08/28 14:15
Cのcallback,C#のdelegateのような処理は C++ではどのように実装するのが一般的でしょうか? class EventHandler { public: void Execute(); virtual; } のようなクラスインスタンスを仲介役に 使うことくらいしか思いつきません・・・
365 :
デフォルトの名無しさん :02/08/28 14:24
moc
templateで、、、
368 :
デフォルトの名無しさん :02/08/28 14:49
アホな質問ですいません。 class Class{ Class(int i) : n(i){} private: int n; }; main(){ Class a(0); Class b(1); b = a; //b.n = 0; } privateなメンバ変数に対して、これが出来てしまうのが腑に落ちなくて…。 デフォルトoperator=は、自動的にfriendになってしまうのでしょうか?
いやoperator=は常に非staticなメンバ関数のはず
>>368 代入を禁止したいのなら、operator=()でもprivateにしたら?
>>369-370 レスありがとうございます。非staticメンバ関数で非friendなんですね。
むはーん、しかしでは何でこんな嫌なことができてしまうのでしょう(;´Д`)
自分でoperator=を定義したときは、friendにするかget系関数を用意しない限り、
privateメンバ変数を参照するのは無理ですよね…。
デフォルトoperator=は特別という解釈で宜しいのでしょうか?
>>371 と、書いているうちにすいません。
ありがとうございます。禁止するときはそうします。
>自分でoperator=を定義したときは、friendにするかget系関数を用意しない限り、 >privateメンバ変数を参照するのは無理ですよね…。 そんなことない。
>privateメンバ変数を参照するのは無理ですよね…。 んなこたぁない
かぶった。そしてみな言い方がおなじw
思い込みが禿げしいと人生損するよ。>>厨さん
>>374-377 ぐぁ、本当だ。皆さんすいません。operator==になってたのと、
インテリセンスで引数相手のメンバ変数が出てなかったのに惑わされました…。
うーん、もう何がなにやら…情報のカプセル化って、
オブジェクトごとではなくて、クラスごとなんでしょうか…。勉強し直してきます。
>>379 撤退するときはうんこもらさないように気をつけよう。
380=379のリンクから漏れた378うんこか?w
383 :
デフォルトの名無しさん :02/08/28 18:01
どうすればオマエらみたいに、プログラミングのプロになれますか?
385 :
デフォルトの名無しさん :02/08/28 18:06
>>384 転職というか、まだ学生なのですが
就職先で教えこまれるのですか?
386 :
デフォルトの名無しさん :02/08/28 18:07
[警告・危険] 2チャンネルでの書きこみは直ちにやめて下さい。 私はここに書き込んだために、アドレス帖の中身を覗き見られました。 これは嫌がらせではありません。 [警告・危険]
みられるほどアドレスありません。 ともだりすくないのれ。
>>384 ごめん、就職って書いてあったな。
眼科いってきます。
そもそもメーラなんて入ってないし….
こりゃだめメーラ。ヽ(´ー`)ノ
>>390 ....................................................................................................(゚Д゚)ハァ?
>>364 boost::function とか Loki::Function とか。
393 :
デフォルトの名無しさん :02/08/29 00:16
はじめまして、C++初心者なのですが質問があります。 クラスの宣言で、例えば class A{ public: void a1(); void a2(); } というクラスを継承して class B : public A{ }; というクラスBを作ったとします。 このクラスBのオブジェクトからは関数a1にはアクセスできるけど 関数a2にはアクセスできないようにしたいのですが、 どのようにすればよいでしょうか? なんだかprivateやらprotectedやらすこし混乱しています。 どうか教えてください。
そのくらい簡単に試せるでしょう?
>>393 基底で公開しているものをパブリック継承先で
非公開にするのは無理だし(出来たとしても)すべきではない。
実装継承するならprivate継承も一つの手だが
396 :
デフォルトの名無しさん :02/08/29 01:08
>基底で公開しているものをパブリック継承先で >非公開にするのは無理だし(出来たとしても)すべきではない。 >実装継承するならprivate継承も一つの手だが 基底では使えるけど継承先で使えない関数を作るのは 無理って言うことなんでしょうか。 いまいち継承の種類も良くわからないのですが・・
private関数
インターフェースの設計をしなおしたほうがいいんでは。
>>396 a1,a2が公開メンバであるのに
継承先で非公開にしたいのはなぜ
class Bで private: using a2;ってやってできない?
>>400 393の文は基底で非公開にしたいように見えるが
402 :
デフォルトの名無しさん :02/08/29 01:29
>>399 なぜかというと、a1の関数の中でやっている処理はそのままクラスBでも
行ないたいのですが、a2の関数の処理は行ないたくないからです。
まあ呼ばなければいいんですが、間違って呼んでしまうことも
有るかもしれないので、Bの変数からは呼ぶことができないように
できればいいなと思ったんです。
403 :
デフォルトの名無しさん :02/08/29 01:32
なんか混乱してきたんですが、やりたいことは 「クラスの変数から関数を呼びたいけど継承はしたくない」 っていうことです。 説明が下手ですみません。
404 :
デフォルトの名無しさん :02/08/29 01:34
クラスの変数っていうのは、メンバ変数じゃなくて class A{ public: void a1(); void a2(); } A a; のような,宣言されたaのことです。
405 :
デフォルトの名無しさん :02/08/29 01:43
もしAのプライベートの属性とかをBでは使ってないなら委譲したらいいかも。 class A{ public: void a1(); void a2(); } class B { private: A a_; public: void a1() { a_.a1(); } } あ、Aのprivateにアクセスしたかったらfriendにしたらいいのね。
406 :
デフォルトの名無しさん :02/08/29 02:00
>>405 ありがとうございます。
なんとか思い通りに動作するようになりました。
皆さんありがとうございました。
>>402 間違い防止なら、これで十分だろ。
class B: public A {private: void a2() {A::a2();}};
とりあえずクラスの自作をして見ようと思う。 自作アプリケーションが雑誌に乗るぐらいプログラムやってきたけど 一度たりともクラスを作った事がない、がはは(涙
410 :
デフォルトの名無しさん :02/08/29 04:53
412 :
デフォルトの名無しさん :02/08/29 07:37
assing
413 :
デフォルトの名無しさん :02/08/29 09:48
∩ | | | | ∧_∧ | | / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ( ´Д`)// < 先生!C++の仕様書の日本語版はありますか? / / \ / /| /  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ __| | .| | \  ̄ ̄ ̄ ̄ ̄ ̄ ̄\ ||\ \ モシ モッテル ヒトイタラ ヒヒョウモ オナガイシマス ||\|| ̄ ̄ ̄ ̄ ̄ ̄ ̄|| ̄ || || ̄ ̄ ̄ ̄ ̄ ̄ ̄|| .|| ||
414 :
デフォルトの名無しさん :02/08/29 09:52
C++って、プログラム言語でなく、業界言語ですか? プログラマや趣味でやってる人はともかく、注坊は使っちゃいけない気がしてきた。 (言語仕様が複雑すぎ)
>>414 リア注でも使おうと思えば使える。DQNは知らんが。
一般にクラスは大規模プログラムに適しているが、小規模プログラムには適していない。
(稀に小規模でもクラス使ったほうが良い場合もある)
だからクラスを使うかどうかは考えた方が良い。
ただクラスを使わなくてもC++を使う価値は充分にある。
オーバーロード、新しいキャスト、名前空間…
少なくともCを使うよりは同じプログラムをC++で書いたほうが良いとも思う。(型チェックが厳しいから)
>(言語仕様が複雑すぎ)
頭に叩き込め。それしかない。
個人でする分にはリファレンス片手でも何とかならんでも無いが。
>>415 > 一般にクラスは大規模プログラムに適しているが、小規模プログラムには適していない。
おいおい…
規模に関係なく、クラス使ってないと管理不能になってしまう漏れは吊ったほうがよいでつか?
そうだね。昔は全て把握できてスパゲッティを量産できたんだが… 最近ちょっと脳が衰えてきた。 OOの弊害だ
使ってないと2ヶ月前のコードが追えなくなるのでクラス必至です。
421 :
デフォルトの名無しさん :02/08/29 20:07
教えてくだされ〜 VC++6でスタティックリンクライブラリを作っています。 グローバル変数のコンストラクタを使ってライブラリの初期化を 自動的に走らようとしているのですが、上手くいきません。 どうも、グローバル変数の初期化単位が、ファイル毎のようで ファイルにアクセス行かないとコンストラクタが実行されないのです。 コレなんとかならないでしょうか? ========== ライブラリコード =========== --- a.cpp --- struct A{ A(){ std::cout<<"A"<<endl; } } g_ob; void test_a(){} --- b.cpp --- struct B{ B(){ std::cout<<"B"<<endl; } } g_ob; void test_b(){} ========== クライアントコード =========== void test_a(); void test(){ test_a(); } main(){} これで "A" は表示されるのですが "B" が表示されません。 なにか良い方法はありませんか?
>>421 クラス定義はヘッダーファイルに書いてインクルードしないとまずいんで
ないかい?
>>421 つーかグローバル変数の初期化タイミングは未定義なので
あてにすんのが間違い。
変数の初期化とか関係なくて、 クライアントコードからb.cppへの参照が無いから、 最適化で落とされちゃってるんじゃないの
b.objはリンクされてないだろうね。 ビルドの設定で.mapファイルを吐かせてみるとよいよ
426 :
デフォルトの名無しさん :02/08/29 21:34
すみません。本当に初歩的な所でつまづいています。 iosクラスのメンバを含むクラスをグローバル領域で定義すると、実行時エラー になるのはなぜでしょうか。コンパイラはBCC5.5.1です。 #include <iostream> class C { C() { std::cout << "C()" << std::endl; } } cc; int main() { } これを実行すると、一般保護違反が出て止まります。
>>426 グローバル変数の初期化の順番は未定義だから。
その例なら、cc のコンストラクタより先に std::cout の
コンストラクタが呼ばれてる保証がない。
428 :
デフォルトの名無しさん :02/08/29 23:17
ファイルを単に1byteづつ読み出したいのですが、 char ch; ifstream in(argv[1], ios::in | ios::binary); in.get(ch); とすると、読み出したいファイル中に2byte文字が存在するとget()は2byte文字を一気に読み込んでしまうのです。 in.read((char*) &ch, 1); としても1文字づつしか読み込んでくれませんでした。 なにか良い方法あありますか?
ifstreamってそんなにインテリジェントだっけ?
430 :
デフォルトの名無しさん :02/08/29 23:55
バイナリオープン。
>>429 ifsreamをいまいち理解できてないのですが、とりあえず2byte文字でも1文字として
読み取るようなので・・
>>430 ifstream in(argv[1], ios::in | ios::binary);
で自分的にはバイナリオープンしたつもりだったんですがほかの方法があるのでしょうか?
2バイト文字の1バイト目だけ読み込まれて、2バイト目が読み飛ばされて しまうということ?
>>427 ありがとうございます。目から鱗が落ちるような思いです。
これを友達に見せて、悩ませてみようかと思います。
>>428 >>431 Cygwin +gcc 2.95.3 および bcc32 で試したが、
ちゃんと1バイトずつで読み込んでいる。
>>432 申し訳ありません。勘違いだったようです。
ちゃん2byte文字部分も2byte目も読み込まれていました。
ただ、単純に
in.get(ch);
cout << (int)ch;
とやると、「A」ならば41と表示されるのに、「あ」ならffffff82(1byteめ)/ffffff82(2バイト目)
となっていました。
お騒がせしました。
>>422 直接、呼び出しているわけではないので多分平気です。
念のため、宣言だけ抜き出してクライアントに
インクルードさせてみましたが、結果は変わりませんでした。
>>423 未定義なのは翻訳単位での初期化順だと思っていたのですが。
mainが呼ばれる前にcpp_init?で初期化されるんですよね。
CPP_UNITでテストの登録とかもグローバル変数のコンストラクタで
やってたと思ったけど、違ったっけ?
>>424 >>425 一度.libに落ちているのですが、それでも削除されてしまうようですね。
未参照グローバル変数の削除は規約上、正当な最適化なのでしょうか。
コンストラクタで何をやっているか分からない以上、リンカで削るのは
無理な気がするのですが。
ライブラリ側のオプションで最適化の抑止は無理っぽいし、
皆さんなら.libファイルの初期化はどのようにやらせますか。
COMみたく明示的に呼び出させるのが楽は楽なんだけど。
>>436 .objをリンクするときに勝手に削除しちゃまずいだろうが、
.libの場合、必要な物を引っ張り出してきてくっつける(リンクする)わけだから、
判断できないんじゃないの?
賢いリンカなら出来るかも知れないけど、オバカなリンカだと
.libすべてをリンクする羽目になるよね。
グローバル変数コンストラクタネタが続くのは集合的無意識の仕業。
>>436 > 未参照グローバル変数の削除は規約上、正当な最適化なのでしょうか。
リンカは参照されないシンボルを削除するんじゃなくて、
参照しているシンボルを再帰的に辿ってオブジェクトを集めるのが仕事
だと思うが、どうか。
>>436 >.objをリンクするときに勝手に削除しちゃまずいだろうが、
.objと.libってリンカの入力として区別されたっけ?
.objと.libってリンカの入力として区別されたっけ? 普通は区別される。 objをリンク指定したばあい、シンボルが参照されていなくてもリンクされるはず。
>皆さんなら.libファイルの初期化はどのようにやらせますか とりあえずやるほうほう。うまいかどうかはさておき。 (1)Cっぽいが安全 XXX_init() と XXX_end() を用意して、利用者に呼ばせる。 コンストラクタの呼ばれる順番に依存しないため、 それに起因するバグに悩む必要がなくなる。精神衛生上よろしい。 (2)C++にこだわる 初期化ルーチンをLIB_Initクラスのinit()メソッドに突っ込む。 LIB_Initクラスのインスタンス(init_obj)をグローバル変数として持たせる。 そのライブラリの関数全てが、最初にinit_obj.init()を呼ぶようにする。 (ライブラリを使う限り、このインスタンスはリンクされる) LIB_Initクラスのデストラクタは、ライブラリの終了処理をする。 (2')init()を遅らせる必要がないなら、LIB_Initのコンストラクタで 初期化し、Lib_Init::check()で初期化の成否を返すようにし、 check()をライブラリの各関数が最初に呼ぶようにすればよい。 2,2'ともに、そのライブラリが全く呼ばれなければ init_objが生成されない。よって気前よくリンクできる。 ただし、同じやり方をする複数のライブラリが相互に参照する場合は 大変面倒なことになったりするので(1)に回帰することもしばしば。
>>435 それは C 言語の時代から有名な、符号拡張の罠です。0xff でマスクするか
unsigned char 使って下さい。
442 :
デフォルトの名無しさん :02/08/31 00:23
>>435 なるほど。ありがとうございます。
素直に0xffでマスクしてみます。
文字コードをcharのまま比較するとマズーとかいう罠もあったな。 if(ch>=0xa0)とかいうような
>>437-439 私のリンカに対する理解が、間違っていたようです。
今まで、グローバル変数が削除されるなんて、思っても見なかったので
今回の件は、かなりショッキングでした。
私も、まだまだ勉強不足のようです。
参考になるレス、ありがとうございました。
>>440 > (1)Cっぽいが安全
やっぱりコレですか。
でも、初期化しなくても死ぬわけではない罠にかかりそうですね。
> (2)C++にこだわる
こっちも考えたんですが、どうせ自分のやることだから
仕様拡張したときに、呼ぶの忘れるだろうと考え直しました。
アドバイスどうもありがとうございました。
うーん、lib_mainが欲しい。
445 :
デフォルトの名無しさん :02/08/31 22:06
質問。 名前空間についてなんですが あるファイルの中で定義されている名前空間を 2つ以上の別のファイルの中で使いたいのですが、どうすればよいのでしょうか。 ヘッダファイルの中に名前空間のメンバを記述して、 使いたいファイルの中でincludeすると、 すべてのメンバに「再定義されています」というエラーが出てしまいます。 レベルの低い質問だと思うのですが、良かったら教えてください。
.h のほうで extern で宣言して .cpp で定義するようにしてはどうか。
447 :
デフォルトの名無しさん :02/08/31 22:30
>>446 ありがとうございます。
解決しました。
本当にありがとうございました。
>>436 最終手段としてCOMにするというのがあるが一般人にはおすすめできない
449 :
デフォルトの名無しさん :02/09/01 09:19
質問があるのです。 VBのSendkeysに相当する命令はC++には無いと思うのですが、 同じようなこと(ウィンドウにキーを送信)をさせるには どうすれば良いのでしょうか? 現在C++をSDKから勉強中で、 できれば、MFCを使わずにできる方法があれば教えていただきたいのです。 よろしくお願いします。
>>449 SendMessageでWM_KEYDOWNとWM_KEYUPを送信しちゃどうだい
あと、これはC++というより、VC++とかWIN32APIとかのスレの方がいいな
SendMessageで漢字って送れるのかな?
>>452 いや、別に勘違いしているつもりはないがSendKeysは漢字を送れるんだよ。
SendKeysと全く同じ物を作るにはどうすればいいのかなと。
keybd_event()
>>454 keybd_eventなら漢字を送れるということ?
>>451 WCHAR test[]=L"逝って良し";
for (int i = 0;i < 5;i++)
SendMessage (hWnd,WM_CHAR,test[i],1);
↑で送れると思うよ。
みなさんありがとうございます。 ところでSendMessageでBackSpaceを送るにはどうすれば良いですか? または、Alt+Cとか?
VK_BACK_SPACE
460 :
デフォルトの名無しさん :02/09/01 23:35
保守
今までクラスを避けて通ってたけど意外と簡単だった・・ オブジェクト指向:塊
オブジェクト指向:魂
オブジェクト指向:塊
オブジェクト指向:醜
465 :
デフォルトの名無しさん :02/09/02 21:40
オブジェクト指向:堺
オブジェクト指向:蜀
>>465 operator=などが一時オブジェクトを生成
↓
デフォルトコピーコンストラクタが呼ばれる
↓
一時オブジェクト消滅
↓
一時オブジェクトのデストラクタが呼ばれる。
↓
Num配列あぼーん
↓
もとのオブジェクトがNum配列参照
↓
プログラムあぼーん
>468 なんとなく感じ分かりました。ありがとう御座います。
>>468 そだね。return *this の時にコピーコンストラクタが呼ばれるのが原因だね。
なんちゅうややこしい言語なんだ。
auto_ptrとかshared_ptrにすれば解決じゃん
なんでこんな単純な物をテンプレートまで持ち出して複雑にしなくちゃならないんだよ。
自前でコピーコンストラクタを書いてやれば解決すます。それだけ。 Effective C++の11項「メモリを動的に割り当てるクラスでは、コピーコンストラクタ と代入演算子を宣言しよう」当たりを参照。
Bignumをそれなりに実装しようとしたら 結構複雑になりますが何か。
> テンプレートまで持ち出して テンプレート使うのがそんな大そうな事か。つかコーディング楽になるもんだろ。
わざわざ頑張らんでもとりあえずはvector<int>で十分だろ。
>>472 shareしたりauto_ptrで破壊したりしちゃったらダメだと思ふ…
(´Д`;)ヾ 473はこれからtemplateやSTL覚える人なんでかんべんしてください。 ∨) ((
C++は普通レベルに使えるまで長くかかる言語だなぁ。templateやSTL必須か。 まさかtemplateやSTLは上級レベルとか言わないよね。
>>481 俺は
>>465 の問題について話してる。これについては否定はしないようだね。
テンプレート自体は「テンプレートは何のためにあるか?」の答え通りに
使えば便利なのは良く分かっている。
(´Д`;)ヾ すいません
∨) 他の言語は
>>465 みたいなオブジェクトのコピーはどう行われるのか
(( このC++厨に教えてください
>>477 俺も vector 使うに一票だが auto_ptr 使うのは、コピーコンストラクタをきちんと
書くという条件の下では、問題ないと思うぞ。shared_ptr も参照カウントをチェック
して copy-on-write できるし。
>>479 楽な分だけ、代償は支払ってるけどな。
>>484 他の言語が何をさすかわからんがJavaやC#等はポインタ(参照)はshared_ptrとか適当なことを言ってみるテスト。
operator=とかの宣言方法なのですが、 const CTimeEx& operator=(time_t t); のようになっている場合があるかと思うのですが、 この最初のconstってどういうことなのでしょうか? 戻り値のCTimeExの参照についてconst指定するって いうのは、thisがconst?などと考えてしまうのですが いかがでしょう? 無知ですみませんが、気になって仕方ないので...
戻り値が変更不可能ということ
thisが指してるオブジェクト(*this)が const
C++4年目でSTL勉強し始めた俺は逝って良しですか?
C++で一度実行をしてexeファイルを作ってから、 プログラムを書き換えてもう一度実行しようとすると 書き込みモードで Debug/Sample1.exe を開けません ってエラーが出るんですが原因として考えられるのはどんなことがあるんでしょうか?
resありがとうございます。 戻り値または、*thisが変更不可能ということは、 定義内で、*thisに代入とかはできないことになるのですか? それとも、戻り値が返された後、代入されたくないときに 指定するということですか?
実行中
>>493 constになるのはreturnを受けた側の話
>>493 >定義内で、*thisに代入とかはできないことになるのですか?
ではなく、単純に返却値を定数扱いするということ。
ふむふむ、なるほど、そういうことでしたか! でも、returnを受けてそれに代入不可能 とかしたいということがあるんでしょうか? 具体的にはa=b=cとかしたくないってことですか? というか、const指定するのが一般的なんでしょうか?
数値をクラスとして考えると 1 + 2 = 1 だめ a + b = c いい(const無し) a + b = c だめ(constあり)
=演算子の返却値を const にするのは代入の途中で値が変わらない ことを保証するため。a=b=c で c と a の値が違ってたら困る。
500
いろいろ細かいことに答えてもらい ありがとうございました。 日々精進します(^^;
503 :
デフォルトの名無しさん :02/09/03 09:36
=演算子のconst性は(a=b)=cには関係するが、 a=b=cには無関係。
>ことを保証するため。a=b=c で c と a の値が違ってたら困る。 auto_ptrわ?
>自前でコピーコンストラクタを書いてやれば解決すます それより operator =() の戻りが、参照になってないから、一時オブジェクトがつくられちゃうってだけでしょ。
506 :
デフォルトの名無しさん :02/09/03 14:54
void foo(A &x); foo(a = b); という場合、const A &operator=()ならエラーになるけど、 A &operator=()なら通る。あと、intの場合(i = 0) = 1 は正当だから、i = 0は左辺値になる。だから、constは この場合付けない方がいい。
constは付けない(前スレで既出だった気がする) 理由はEffectiveC++読むこと
>(a=b)=c >(i = 0) = 1 これは不定じゃないか?
509 :
デフォルトの名無しさん :02/09/03 16:32
newをmallocみたいなものだとした場合、これに対するreallocみたいなものはないですよね?
>>509 STL使ってれば全然そんなこと考えない。
>>510 702って何だろう?801みたいなもんか?072の間違い???
STLコンテナのresize?
ふつーにvectorでいいんでない?
vectorは重いからイヤです
おまえらnewで何の領域を取りたいのか聞けよ
効いてほしけりゃはじめからそう書け
>515 貴様は本当に計ってみたのかと小一時間・・
519 :
デフォルトの名無しさん :02/09/04 10:23
そりゃ関数の引数や戻り値にそのままvector使ったりしたら重いわな。 そういう用途ならauto_ptrでも使っとけ。 ローカル変数やメンバ変数にするなら、重いはずは無い。 処理系によっては、むしろ型の情報を使った最適化が行われていて、 速くなるかも知れない。 何か理由があって、vectorを使えないなら、生のメモリが欲しいのか、 コンストラクト済のメモリが欲しいのかによってやり方は変わる。 前者なら直接malloc/realloc呼ぶのが正解。後者なら、もう1つ配列を new[]して地道にコピーするのが正解。 malloc->construct->reallocでも良さそうだけど、reallocは コピーコンストラクタを呼ばないで、単にメモリコピーをしてしまうから、 正しい挙動にするには、malloc->construct->malloc->construct->free という手順を踏まなければならない。つまり、reallocみたいにコピーを 省略するのは無理。それならnew[]の方がまし。
520 :
デフォルトの名無しさん :02/09/04 11:50
あるプログラムのデバッグをしているのですが 必ずある時点でAborted(core dumped) となって止まってしまいます。 通常のデバグの方法ではなかなか原因が検出できなくいきづまってしまいました そこでcygnin上で動かしているgccが吐く ***.exe.stackdumpを調べれば原因がわかるかもと思っているのですが、 ちょっと読み方がわかりません。 これの便利な使い方ってどうやるのですか? ちなみに簡単なアセンブラやレジスタの仕組みなどはわかります。
>>520 gdbだ. ヒントだけあげるから自分で調べて.
523 :
デフォルトの名無しさん :02/09/04 21:02
SDKのファイル・フォルダセキュリティ設定に関して質問があります。 AddAccessAllowedAceEx関数を使用し継承を設定したのですが、設定したフォルダの中に新しいフォルダを作成すると「継承元なし」のフォルダが出来てしまいます。 継承元を親フォルダに設定するにはどうしたらよいでしょうか? OSはWindowsXPで、VC++のバージョンは6.0です。
>>523 スレ違いだボケ
win32apiスレに行け
525 :
デフォルトの名無しさん :02/09/04 23:11
class A { int a; int b; void show() { printf("a:%d b:%d", a, b); } }; 上のようなクラスがあり、そのインスタンスを複数作った場合、 show()のためのメモリも複数確保されるのでしょうか? 厨な質問ですみません。
二つの自然数a,bの最大公約数を求めるプログラム
>>525 show()自身により消費されるメモリはそのコード本体のみ。
インスタンスを作ろうが作るまいが関係ない。
>>527 クラス内に関数を定義するとinline宣言だから違うかもよ?
もっともクラス毎ではなくて、呼び出し毎になるが。
>>528 inlineされたとしても、コード本体のみ
という表現に間違いはないと思いますが...
532 :
デフォルトの名無しさん :02/09/05 01:53
#include <iostream> class A{ public: A(){m_a=3;} protected: int m_a; }; class B{ public:int func(){ class fl_A: public A{ public: void operator=(const A &in_A){ A *a_A = this; *a_A = in_A;//ダメポ… } int Get_m_a(){//B::m_A::aにアクセスしたいけど、friend関数は使いたくない。 return m_a; } }; fl_A a_flA = m_A; return a_flA.Get_m_a(); } private: A m_A; }; int main(){ B a_B; std::cout<< a_B.func()<<std::endl;; return 0; } クラスBのメンバのインスタンスAのprotectedなメンバにアクセスしたいのですが、 friend関数を使わずに無理やり実装したのですが、 多分、処理系依存とかだと思うのですが、どういう風にコンパイラは解釈するのでしょうか… おとなしくfriend使って実装するつもりですが、気になったので教えてください。
間違えました。 fl_A a_flA = m_A; ↓ fl_A a_flA; aflA = m_A; 初期化と代入を間違えました。
>>532 int func()内の、fl_A a_flA = m_A; だけど、これはコピーコンストラクタがないと
コンパイルできないよ。
fl_A a_flA;
a_flA = m_A;
と二行に分けたら?
あららら
>>532 処理系依存と書きながら処理系を指定しないのはどうして?
>>536 と言うか、文法上?の誤りを指定して欲しかったのかな…
この書き方だとコンパイラーがこういう風に解釈しても構わないから、
こう言う風になってバグが発生するみたいな…
一応コンパイラーはMS Visual C++ Professional 6.0 sp5を使っています。
それだったら、コンパイラはデータメンバのうちpublicとprivateの順序を 自由に変えてよいから、fl_A a_flAとA m_Aの順序が入れ替わるかも しれない、というのはダメ?
>>538 良いです!
つうかそんな卑怯な仕様があったのですか(笑)
なるほど
それなら確かに駄目ですね。
しかし、c++って深いですね…
>>539 今ソース探してるから、信じるのは後にしてね。
どっかで見たんだよなあ・・・・コンパイラは、private、public、protectedの 各々のデータメンバをまとめることがあるから、データメンバの並び方に 依存したプログラムを書いてはいけない、という文を。
>>541 でも本当っぽいですね…
自分も少し探してみましたが見つかりませんでした。
522 ありがとうございますgdbを使用して だいたいの原因を切り分けられるようになりました。 しかし今度は実行時にsignal6エラーを吐いて失敗するようになりました。 このエラーはなんなのでしょうか?検索エンジンで調べても不思議なほど 情報が少ないですね。 別に珍しいエラーではないと思っているのですが・・
>>532 のソースと
>>538 のソースの関係が見えません。
> fl_A a_flAとA m_Aの順序が入れ替わる
って、 a_flA はローカル変数で m_A は B のメンバですよね?
ローカル変数に public も private も関係ないし、
入れ替わるってどういうこと?
バイナリレベルでのメンバの配置が public や private の影響を 受けるというのと混同してるのでは。
549 :
デフォルトの名無しさん :02/09/06 11:04
vector vec; して myClass *myclass = new myClass("test"); vec.push_back(vec); したばあい vec.clear()で廃棄おっけーですか? それともdelete vec[0]が必要なのでしょうか? これだと結局vectorの要素一つ一つを回していかないといけませんよね?
deleteが要ります。 いやならスマートポインタ使え。イジョ。
スマートポインタつっても std::auto_ptr はだめだぞ。イジョ。
552 :
デフォルトの名無しさん :02/09/06 17:49
なんか、ここで答える人達って 「タイシタコトナイヨネ」
どういう答えが聞きたかったのですか。 たいしたことある答えが必要なら、たいしたことある質問してください。
554 :
デフォルトの名無しさん :02/09/06 18:01
いま552はムキになって長文の質問を(しかもわざと難しく)書いている最中です。
vector vec; vec.push_back(vec);
557 :
デフォルトの名無しさん :02/09/06 18:45
#include <iostream.h>#include <string.h> struct charactor{ public: float posX,posY; }; class CLeft{ public: charactor *C; void SetP(charactor *Chara){C=Chara;} float GetP(){return C->posX;} }; class CRight{ public: charactor Own; CRight(CLeft cl,float px){Own.posX=px;cl.SetP(&Own);} }; int main(){ CLeft cl; CRight cr(cl,1.0f); cout << cl.GetP() ; return 0; } コンパイルは通るのですが、これを実行すると、エラーが出てしまいます。 構造体のポインタを宣言したところがまずいようなのですが、何が悪いのか 自分ではわかりません。アドバイスお願いします。
値渡しになってるよ。 CRight(CLeft& cl,float px){Own.posX=px;cl.SetP(&Own);} ~~
559 :
デフォルトの名無しさん :02/09/06 19:26
無事解決しました。ありがとうございます。 しかし、なぜこの状況でアドレスで引数を宣言しないといけない理由が わかりません。もっと精進して参ります。
>>557 プリプロセッサ命令は一行に複数書くなよ。変だよ。すごく変だよ。
>>557 値渡しだとCRightのコンストラクタを呼び出す際に、CLeft型の一時変数が
作られ、それが渡される。
そしてSetPはこの一時変数のアドレスをcharacter *Cに代入するため、コン
ストラクタの実行が終わった時点で一時変数は消去され、*Cはダングリング
ポインタとなる。
このポインタに対しGetP()を起動すれば何が起きてもおかしくない。
>>561 と思ったが、微妙に違ってた。
cl本体の*Cには何も代入されてない状態でGetPを呼び出しているのでした。
だから何が起きてもおかしくない、と言い換えます。
>>557 関係ないですが、#include <iostream>は使えないのですか?
>>557 はJavaをやってたんじゃないかと推測。
565 :
デフォルトの名無しさん :02/09/06 23:33
質問です。Visual C++6.0にて void main() { ifstream ud; ud.open("test.dat"); if(ud.bad()){ cerr<<"can't open file\n"; } ud.close(); } を作成・実行すると、"test.dat"なるファイルが存在しないにもかかわらず、なぜかサイズ0の ファイル"test.dat"を勝手に作成して、 if(ud.bad()){} を素通りしてしまいます。 どうすればファイルを勝手に作らないように出来るでしょうか?
ios::nocreate
567 :
デフォルトの名無しさん :02/09/06 23:49
>566様〜、解決しました。多謝。 ud.open("test.dat",ios::nocreate); if(ud.fail()){…}
568 :
デフォルトの名無しさん :02/09/06 23:54
ライブラリ等を作りたいときに、 Cでいろいろ関数を書いて、DLLにしておけば VBなどで呼べますよね なら、C++でクラスを用いてライブラリを書いたとき COMを使わずにVBから呼べるDLLって作れるんですか?
569 :
デフォルトの名無しさん :02/09/06 23:55
■10.000円の高額収入
1件につき最大10.000円の高額収入。月収100万円以上も可能。
■画期的なビジネス!
インターネットを利用したこれまでにない斬新で画期的なビジネスです。
■誰でも出来ます!
インターネットができる環境の方なら誰でも参加可能です。
インターネットを利用したビジネスですので、自宅や会社で好きなときにで
きるビジネスです。
■専門的な知識は一切不要!
ビジネスに必要なツールは全て当社で用意いたします。
また、サポートも万全です。
■詳細は今すぐこちらから
http://www.bea.hi-ho.ne.jp/paisen/
っていうか、誰がvoid main()なんて広めたんだよ…。 int main(int argc, char **argv)だろうがと小一時間(略 // int main(int argc, char **argv, char **env) ってのもあるね。
VC++的には合法だからだろ<void main()
悪い習慣が何でもVCのせいだとは恐れ入った。
>main 関数および wmain 関数が void 型 (戻り値なし) を返すように宣言することもできます。 VC++6.0のヘルプから抜粋。
574 じゃないが、
>>575 それが本当に void main() と書くヤツがいる「原因」なのか?
class AA : public A; A *a; があって ((AA)(a[i])).foo (); はダメで ((AA*)(a))[i].foo (); はOKなのは何故でしょうか?
>((AA)(a[i])).foo (); AからAAへの変換コンストラクタが必要 >((AA*)(a))[i].foo (); A*からAA*にstatic_castされる。 コンパイルできるからといってOKとは限らない
579 :
デフォルトの名無しさん :02/09/07 09:24
>571 だって、小規模なテストするには楽なんだもん…
void main(void)で教わりました。 多分ああいう教師のせいだと思います。 もちろん私はdouble main()にしていますが。
581 :
デフォルトの名無しさん :02/09/07 09:31
>>579 void main()よりもint main()の方が短くていいじゃん。
mainのreturnは省略してもいいんだし。
582 :
デフォルトの名無しさん :02/09/07 09:57
void main() で書いてある本があるからだろ。 void main() でもエラーでないんだし
double main()でもFILE *main()でもエラーは出ない。 VC6なら警告も出ないね(/W4)
ここはまた main() を議論するスレになったんですか?
int main() int main(int, char **) int main(int, char **, char **) これら以外は main() と認められず。
586 :
デフォルトの名無しさん :02/09/07 11:29
グローバルなクラスのインスタンスは いつコンストラクタが呼ばれるか不定という話がありましたが グローバルなクラスのポインタ(Class* ctest;)を用意して mainでインスタンス生成(Class c;)→ポインタコピー(ctest = &c;) extern Class* ctest;で別モジュールから弄ったりしたら 怒りますか?
587 :
デフォルトの名無しさん :02/09/07 11:30
>>585 C++ではint main(int, char **, char **);も認められたのか?
>>586 「main に入った時後、最初に使う瞬間」にならどのグローバルインスタンスも
初期化されていることは保証されてように読めるので、それは
あまり意味がないのではなかろうか。
> [3.6.2]
> It is implementation-defined whether the dynamic initialization
> ...(略)... is done before the first statement of main or deferred to
> any point in time after the first statement of main but before the
> first use of a function or object defined in the same translation unit.
>>586 main以前にctestを使わなければ問題ないのでは?
でも、もしそうなら別に実体でも構わないと思うけど・・・
>>585 Embedded C++/C99ではvoidも認められてはずですが何か?
>>586 Cやその他のライブラリ関数を使わないなら問題ない
>591 実は、初期化とか面倒なウィンドウの生成と DirectDrawをひとまとめにしちゃって 他のモジュールからはDirectDrawオブジェクトのインスタンスしか 見えないようにしたいナァという話なのです
>>590 freestanding まで視野に入れて議論するのは無意味だろ。そもそも組み込み系
だと「終了してはいけない = main から return した瞬間にハングアップ」とか「エン
トリポイントが main じゃない」とかもアリアリだから。
hosted environment では C99 でも main は int のみ。以下、規格書から抜粋。
> 5.1.2.2.1 Program startup
> 1 The function called at program startup is named main. The implementation declares no
> prototype for this function. It shall be defined with a return type of int and with no
> parameters:
>
> int main(void) { /* ... */ }
>
> or with two parameters (referred to here as argc and argv, though any names may be
> used, as they are local to the function in which they are declared):
>
> int main(int argc, char *argv[]) { /* ... */ }
>
> or equivalent; or in some other implementation-defined manner.
594 :
デフォルトの名無しさん :02/09/07 15:02
>>593 組み込み系まで視野に入れて議論するのは無意味だろ。
>>594 俺に言うなよ。void main() が OK っつーのは freestanding の話で、即ち
組み込みなんかも視野に入れての意見なんだから
>>590 に言ってくれ。
っていうか大人しくint main()にしろよ。voidからintに改めるのがそんなに面倒なコトか? 無難な方法を使うってことができないのか?
597 :
デフォルトの名無しさん :02/09/07 16:48
俺は自分のスタイルを貫き通す。これがポリシー。 自分を捨てたプログラミングなんて、やってらんない。 だから俺はいつでも void main(void)。 没個性プログラマーは、社会の歯車になって埋もれてしまえばいいよ。
なんでも個性と呼ぶのは問題だろ、現実を見ろ…とネタにレス。
>>597 創造性がない奴に限って、どうでも良いところで差別化を図りたがる(w
なるほど。だから
>>597 には仕事が来ないのですね。
601 :
デフォルトの名無しさん :02/09/07 17:30
602 :
デフォルトの名無しさん :02/09/07 17:31
来月のUNIX Magazineの特集は「個性派プログラミングで差をつけよう!」 らしいよ。注目だね。
>>597 そろそろ「釣れた」と書いて逃げる頃合でしょうか?(^^)
604 :
デフォルトの名無しさん :02/09/07 19:02
すみません。 マイクロソフトのC++でアプリの作製方法等を詳しく解説した HPありませんか? なかなか見つからないので、お願いいたします。
猫でもわかる
釣れすぎワラワラ
間違っているとは思えないんだが、 オブジェクトの作成ではなくオブジェクト用のメモリ確保と初期化って事か?
ありがとうあなたは良い人です。(@@)うるうる(感動している)
安心しますた。
new演算子を使うとメモリ領域確保と同時にコンストラクタ呼び出せる から便利だね。mallocだと明示的にコンストラクタ呼び出さないといけ ない。
delete NULL;を必ず1ソースに1つは含める。 これが俺のPolicy!
(-_-)
delete ptr; としたあと ptr = 0; とするのなら二重deleteを防ぐ意味の上で 有効なテクだろうが、delete NULL; の必要性がわからない。
>>614 ::Sleep(0)(あるいは1)なら分かるけど
delete NULL は型がわからないからコンパイル通らないと思った
620 :
デフォルトの名無しさん :02/09/08 00:04
昨日,すれ立てるまでもない…に投稿したけど,レスがつかなかった のでこちらに投稿させていただきます. C++で数値計算のプログラムを書いてます.ある変数(double型)を volatileをつけて宣言した場合と,そうしなかった場合で,計算結 果が異なってしまいました.コンパイラによる最適化が問題かと思 い,最適化しないようにオプション(-O0)をつけてコンパイルしたの ですが,結果は変わりません.これはコンパイラのバグでしょうか? あるいは,C++の仕様の範囲内でしょうか?コンパイラはg++を使用し ております.
それ以前の問題でNULLは整数リテラルの0だからdeleteできないのが普通だろ。
622 :
デフォルトの名無しさん :02/09/08 00:12
>>620 なぜvolatileをつける必要がある?
>>620 volatile をつけた時と、つけない時でどっちの結果が正しいの ?
また、マルチスレッドは使ってるの ?
NULLマクロを使うには cstddef をインクルードする必要がある。
>>620 volatileは本来の変数の値には影響しない。g++のバージョンとCPUの組
み合わせによるバグかもしれない。
お返事ありがとうございます.
>>622 元々,同じ計算を実行する(と私が思っている)ソースが2つあるのですが
2つの計算結果が違ってしまったんですよ.いろいろ検証してみた結果,
問題の変数が,一方ではグローバル変数,もう一方ではメンバ変数になっ
ているのが原因らしいということがわかりました.で,メンバ変数の方を
volatileつけて宣言するか,定数に置きかえれば,2つの計算結果が完全
に一致したわけです.私としては,最適化の副作用かなと思って,-O0と
してみたわけですが,これは効果なしでした.
>>623 どちらが,正しい結果かはわかりません.また,マルチスレッドでは
ありません.コンパイルして,ターミナル上から 普通に(?)実行して
います.解いているのは微分方程式です.非線形項が入っているとは
いえ,同じ計算機で,みため同じソースなので,同じ計算結果が出ない
とおかしいと思うのですが.レジスタに割り当てられる際に値が変更
されることも考えにくいし,丸め方か何かが影響しているのでしょうか.
>>624 gccの2.96とPentium3で主に実行していました.CPUのバグも
疑って,Pentium2,Pentium4で実行してみましたが,改善され
ませんでした.gccをバージョンアップした方が良いのでしょうか.
627 :
デフォルトの名無しさん :02/09/08 00:35
>>626 2.96でそんなバグは聞いたことがないけどなあ。Pentium3ならなおさら
バグはないでしょう。
3.2が出ているからバージョンアップしてみるのも手です。
>>625 その違いって、誤差レベルなの ? だったら、計算順序による丸め誤差の
影響はありえる。(丸め誤差については、C++ の仕様の範囲外。)
テンプレートの一部だけ特殊化って出来ないですか? template<class A, class B> class C { ...; }; template<class T> class C<int, T> { ...; }; と言う感じで
>>620 文面から見る限りではvolatileで何かが変わるとは思えないし、コンパイラのバグもそうそうあるものじゃない。
ソースを見ないとなんともいえないけど、ステップ数はどのくらい?
どっかに上げれば暇だからみてもいいよ。
とりあえず前後のポインタ操作にバグがあったりはしないか?
633 :
デフォルトの名無しさん :02/09/08 00:56
質問です。 VC++6.0にて配列を作るのに、一次元ならば double *test; test = new double[2]; … delete[] test; test=NULL; で実現できるのですが、二次元以上になるとエラーが出てきて実現できません。 一体どのように解決すれば宜しいのでしょうか?よろしくお願いします。
635 :
デフォルトの名無しさん :02/09/08 01:00
>>633 二次元以上は自分で確保する
char **pStr = new char[5];
pStr[0] = new char[100];
.
.
.
>>628 ありがとうございます.試してみます.
>>629 差は時刻とともに爆発的に増大します.系の性質から,微小誤差が指数
関数的に拡大することは承知しています.ですが,表面上同じコードが
volatileをつけるかつけないかで,違う結果を出すといったことがある
と,コンパイラのちょっとしたさじ加減で,異なる計算結果が得られて
しまうかも〜と不安になりまして.
計算順序はソースレベルでは同一です.丸め誤差がC++の仕様の範囲外
ということは,丸めに関しては,コンパイラあるいはCPUに依存すると
いうことでしょうか.
俺にはC++という素晴らしい彼女がいるのに・・・ 体が満たされないってこういうことを言うのね(涙
>>636 > 計算順序はソースレベルでは同一です.
かなり注意深く書いてないと、ソースレベルで計算順序なんてわからない
ぞ。
> 丸めに関しては,コンパイラあるいはCPUに依存するということでしょ
> うか.
あたり。
とりあえず、gcc なら long double とかが使えるらしいので、試してみ
たら ?
639 :
デフォルトの名無しさん :02/09/08 01:13
>>635 レス有難う御座います。が、やはりできません。
double **test = new double[i];
はもちろんのこと
double **test = new *double[i];
もエラーで弾かれてしまいます…
double** p = new double*[i];
これだと少なくとも誤差は出ないね。g++2.96 + Pen3 #include <fstream> int main() { double d = 1.000001, dd = d; volatile double e = 1.000001, ee = e; std::ofstream of("test.txt"); for (int i = 0; i < 1000000; i++) { of << d << ' ' << e << ' ' << d - e << std::endl; d *= dd; e *= ee; } }
642 :
デフォルトの名無しさん :02/09/08 01:23
>640 おおおぉ〜!いけました。哀れな初心者に親切なご指導を有難う御座いました!
>>622 ありがとうございます.ですが,ソースは,見せると素性がばれ
ますのでお見せできませんm(__)m.ステップ数というのは「ステ
ップ」の意味を存知ませんので,いくつかわかりませんが,ソース
の中では,微分方程式を解く際の刻み幅500個分の計算を行っています.
250個めまでは,ほぼ一致しますが,以後は全く解の軌跡が異なります.
お返事頂いた皆様に感謝します(わざわざプログラムまで書いて頂きまして).
皆様のお返事を見ていると,問題は,丸め誤差であって,volatileをつ
けて計算結果が一致したのは,副次的な作用に過ぎないようですね.
そもそも,このような計算が,私の目的に沿って必要なことかどうかと
いうこと自体を,改めて考えなおす必要もありそうです.
というわけで,今日は(勝手ながら)ここらで収束させて頂きます.
また,何かありましたら,お願いいたします.
>>643 ステップ数はおおざっぱに言えば、ソースプログラムの行数のこと
微分方程式を解くというと、パッと思いつくのはオイラー法かルンゲ・クッタ法 だなあ。特に難しい事はしてなかったように思うんだけど。
>>636 俺ならアセンブラコードを出力させて、差を追ってみるけどな。
-Sオプションを付けてコンパイルしみたけど、何やら面妖なソースを 吐き出しました。 movl%ebx, -320(%ebp) movl%esi, -316(%ebp) fldl-320(%ebp) movl-300(%ebp), %eax addl$16, %esp fmullLC0 incl%eax movl%eax, -300(%ebp) fstpl-320(%ebp) fldl-32(%ebp) fldl-40(%ebp) movl-320(%ebp), %ebx movl-316(%ebp), %esi fmulp%st, %st(1) fstpl-32(%ebp) jmpL42
>>613 C++には、デストラクタの呼び出し方法は存在するけど、コンストラクタのそれは存在しないだろ
これがnon-volatileの計算部分 movl%ebx, -304(%ebp) movl%esi, -300(%ebp) fldl-304(%ebp) movl-284(%ebp), %eax addl$16, %esp fmullLC0 incl%eax movl%eax, -284(%ebp) fstpl-304(%ebp) movl-304(%ebp), %ebx movl-300(%ebp), %esi そしてこちらがvolatileの計算部分です fldl-32(%ebp) fldl-40(%ebp) addl$16, %esp incl%ebx fmulp%st, %st(1) fstpl-32(%ebp) jmpL42 volatileと指定すると一度FPUにデータを読みとった後mulを実行している ように見えます。
ちなみにLC0というのは定数データとしてコンパイルされています。 LC0: .long208632331 .long1072693249 volatileではこのような不変の値をも変数として扱うようにするようです。
>>648 確かにそうですね。やるとすればコンストラクタと同じ中身を持つ関数を
定義しておいて、それを後から呼び出すしかないですね。
mallocのポインタnewにわたせば?
placepent newを使うのか・・・・トリッキーだ・・・
>618 naru
>>648 コンストラクタの明示的な呼び出し方はあるだろ。
A* a;
a->A::A();
>>630 C++標準ならできるが、Visual C++ならできない。
この場合はインナークラスで代用することはできる。はず(笑)
template<class A, class B>
class C
{
template <typename T> class sub {
public:
B func(T a) { ... }
...;
};
template<> class sub<int> {
public:
B func(int a) { ... }
...;
};
sub<A> impl;
public:
B func(A a) { return impl.func(a); }
};
>>657 そうですか…
無名の共用体とか引数の違うコンストラクタがあるんで
インナークラスでは回避できなさそうです。
どうもありがとうございました。
すいません。その方法で回避できそうです。 感謝感激です。
>656 何これ。
動かんぞ。 #include <iostream> #include <cstdlib> #include <cstring> class A { char* ptr; public: explicit A(char* str) { ptr = static_cast<char *>(std::malloc(strlen(str) + 1)); } operator char*() const { return ptr; } ~A() { std::free(ptr); } }; int main() { A* ap = static_cast<A*>(std::malloc(sizeof(A))); ap->A("string"); std::cout << *ap << std::endl; ap->~A(); free(ap); }
662 :
デフォルトの名無しさん :02/09/08 11:51
ap->A("string")って何? new(ap)("string")だろ。
VC6で動いたよ #include <iostream> #include <cstdlib> #include <cstring> class A { char* ptr; public: explicit A(char* str) { ptr = static_cast<char *>(malloc(strlen(str) + 1)); strcpy( ptr, str ); } const char* c_str() const { return ptr; } ~A() { free(ptr); } }; int main() { A* ap = static_cast<A*>(malloc(sizeof(A))); ap->A::A("string"); std::cout << ap->c_str() << std::endl; ap->A::~A(); free(ap); return 0; } つーか、素直にoperator new オーバーロードしようぜ
おっと、new(ap)A("string")ね。
>>649-650 コンパイラが volatile を正しく処理しているようにしか見えないが
>>636 殆どの CPU では、処理のわずかな違いで計算結果が変わってしまう。
なお、大抵のコンパイラでは、計算精度を一定に保つオプションがある。
内部表現のbit数とメモリにストアしたときのbit数の違いかもしれないと 疑ったけど、-O0すると必ずメモリにストアするから違うねえ・・・
>>667 x87 って、確か浮動小数点レジスタの精度は 80bit (double の 64bit より長い)
あったよね。
64bit の即値とかけ算する fmull と、80bit レジスタ動詞でかけざんする fmulp
で精度に狂いが出てるんじゃないの?
ロードするときは64bitだからそれはないと思う それから-O0やvolatileだったら、計算するたびにメモリにストアするから その都度64bitになってる筈
>>656 ダウト
ANSI C++ の規格書から抜粋。
> 12.1 Constructors
> 1 Constructors do not have names. ...
> 2 ... Because constructors do not have names, they are never found during name lookup; ...
クラス A のコンストラクタは A() という名前では呼べません。
素直にnewインクルードしてplacement new使えよ… 嫌ならこういう関数でも書くか? template< typenameT > inline T* CallConstructor(T& instance) { return new( &instance ) T; }
>>671 instance を最初期化であぼーんだな、そりゃ。
674 :
デフォルトの名無しさん :02/09/08 22:35
テンプレートの引数に型ではなく値を指定する事ってできないのでしょうか? 下記のような事がしたいです。(擬似コード) template<class T, const_value V> class hoge { public: static T s = V; static T getClassValue() { return s; } }; よろしくお願いします。
>>674 テンプレにしなくても、コンストラクタにでも渡すようにしたら?
>>674 template<class T, T V> でどう?
T にclass型は渡せないけど。
渡せるのは、組み込み型ならいけるんだったかのぅ。
ポインタ型のときはその値は外部リンケージが要る。
678 :
デフォルトの名無しさん :02/09/08 22:55
あるクラス A について、 A a = 初期値; と A a(初期値); って同じ物だと思っていましたが、もしかして動作がちがうのですか?
>>675-677 みなさんレスありがとうございます。
実は渡したいのは関数ポインタ、それもメンバ関数ポインタなのです。
「プロパティ」みたいなテンプレートクラスを作りたいのですが…。
>>678 explicitを付けてコンストラクタを定義すると、前者の形は使えなくなる。
さらに追加で質問です。
現在は
>>675 さんの案のようにコンストラクタで渡す方式(動的バインド)で
試しているのですがこれも現状うまくいっていません。
クラスの宣言の中では、そのクラス名ってテンプレート引数に渡せないのでしょうか?
VC6 だと
error C2027: 認識できない型 'ClassName' が使われています。
のようなエラーが出てしまいます。
下記は試している途中のコードです。
template <class Subject, class MemberFunc> class MemberFuncCaller
{
private: Subject& subject_;
private: MemberFunc operation_;
public: MemberFuncCaller(Subject& subject, MemberFunc operation)
: subject_(subject), operation_(operation){}
public: void Do(){ (subject_.*operation_)(); }
};
class User
{
typedef void (User:: *UserFunc)();
public: inline void MemFunc(){ printf("Do it, ok!\n"); }
// ここでコンパイルエラー
MemberFuncCaller<User, User::UserFunc> DoObject(user, &User::MemFunc);
};
解決策をご存知の方よろしくおねがいします。
>>680 なるほど。ということは、前者は
A a(なにか);
a = 初期値;
と同じになるわけですか?
>>679 こんな感じか?bcc5なら通った。
あと、VC6でtemplateを使いまくるのはかなりキッツイので覚悟した方がいいぞ。
template
<
typename Value,
typename Class,
Value (Class::*Getter)(),
void (Class::*Setter)(Value)
>
class property { ... };
//property<std::string, SomeClass, &getName, &setName> name;
>>682 その通り。
>A a = 初期値;
コピーコンストタクタが呼ばれる
>A a(初期値);
直接初期化 A::A(初期値)が呼ばれる
ただし、RVOによりコピーコンストラクタは省略されることもある。
explicitは初期値がA型なら問題ない筈
こういうことかな。 #include <iostream> class A { int x; public: explicit A(int i) { x = i; } void print() const { std::cout << x << std::endl; } }; int main() { A a(1); //A b = 2; //エラー A b = A(2); a.print(); b.print(); }
>>684 なるほど。ありがとうございます。
要するに、両者は違うものだが、最適化で同じになりうる、という認識で。
>>674 なんか割り込んでたみたいですみませんでした
>>679 ,
>>683 プロパティということは、メンバ関数をオーバーロード
している?
たしか、多重定義されているメンバ関数のポインタは、
テンプレートの引数として使えないはず。
>>683 VC6 だと property のインスタンスの宣言時に「特殊化」のエラーが出ます。
メンバ関数へのポインタから通常の関数へのポインタへの変換ができない
という内容みたいです。
特殊化も、メンバ関数ポインタから通常の関数ポインタへの変換もしてないのですが…。
>>687 いえ、メンバ関数は一個です。
現状の悩みは
>>681 でも書きましたが、
このクラスを利用したいはずの、利用側クラスの内部に宣言が書けない事です。
相変わらず 認識できない型 'ClassName' が使われています が出てしまいます。
ひとつ勘違いしてました。 メンバ関数ポインタから関数ポインタへの変換ができないというエラーは出ません。 でるのは error C2973: 'property' : テンプレートの仮引数 'Getter' が無効です。 でした。 さっきのエラーは Value (Class::*Getter)() を書き間違えて Value (*Getter)() とした為にでていました。
690 :
bloom :02/09/09 00:14
>>681 > // ここでコンパイルエラー
> MemberFuncCaller<User, User::UserFunc> DoObject(user, &User::MemFunc);
これって typo?
MemberFuncCaller<User, User::UserFunc> DoObject(User, User::UserFunc);
ではなくて?
>>681 ちゅーかよく見たらあーた、クラス定義の中で
コンストラクタは呼び出せないよ、そりゃ。
× MemberFuncCaller<User, User::UserFunc> DoObject(user, &User::MemFunc);
○ MemberFuncCaller<User, UserFunc> DoObject;
○ User() : DoObject(*this, &User::MemFunc) {}
昨夜はどうもありがとうございました.解決策が2つみつかりました.
>>668 などで指摘されている通り,double型(64ビット)の変数がレジスタ
(80ビット)に割り当てられた際に,余分な桁がまぎれこみ,計算結果に
違いが出たようです.
私が思いついたのは次の2つで,結局,2を選択しました.
1. g++のコンパイルの際に-ffloat-storeオプションをつける.
これにより,double型(64ビット)変数のレジスタ(80ビット)への割り
当てを抑制できました.
2. double型の変数をlong double型で宣言しなおす.
もともとlong double型は80ビットですので,レジスタに割り当てても
不要な桁が入りこまないようになります.
ちなみに,計算速度は,1,2で,大きな差はありませんでした.
>>691 ???? テンプレートじゃない普通の引数に型名ですか?よくわかりません。
>>692 しまった。この間仕事で Java とか使ってたので宣言時に初期化できるような気になってました。
これを適切に直しても VC6 だと利用側のクラス名を判別できないエラーが出ます。
bcc ならできるとの事なので、いまインストールしてみたのですが、たしかにコンパイルできますね。
ところで、この場合、Getter と Setter はどうやって使えばいいのでしょうか?
template <typename Type, class ClassName, Type (ClassName::*Getter)(), Type (ClassName::*Setter)(Type)>
class property
{
private: Type m_Value;
public: ClassName x;
public: Type& operator= (const Type& rhs){ return (x.*Setter)(rhs); }
public: operator Type() { return (x.*Getter)(); }
};
class User
{
private: int v_;
public: int Get(){ return v_; }
public: int Set(int v){ v_ = v; }
property<int, User, &User::Get, &User::Set> ValueProperty;
public: User() : ValueProperty(){}
};
としてmainとかで
User user;
user.ValueProperty = 50;
printf("%d", user.ValueProperty);
こうすると、未定義の構造体 'User' というエラーが出てしまいます。
なぜでしょうか?
>>693 うーん、そうだとしても、-O0で、volatileとそうでないものに違いがでる
というのは納得行かんなあ・・・
まあ解決して何よりなんだけど・・・
>>692 ,
>>694 DoObject(…) ってのはメンバ変数定義(のつもり)かよ…。関数宣言かと思った。
>>696 よく Java や C# とごっちゃになるんです。
まんま Java/C# 式のまちがいをした時は
「へんてこな純粋仮想関数の宣言です!」とか怒られるんですよ。
今日はもう寝ます。みなさんありがとうございました。
質問者が寝てしまっても、次にきた時の参考になるように
アドバイスを残してくださる優しい方がいた時のためにあらかじめ
書いておきます。
ありがとうございます!
698 :
デフォルトの名無しさん :02/09/09 01:24
どうでもよさげな話で恐縮だが、クラスの中身ってpublicから書く? それともprivateから書く?
どうでもよすぎ。 見た目効率〜とかいうスレがあったと思うからそっち逝け。
>>698 public -> protected -> private
全部pからはじまるのがむかつく。・・・・なんとなく。
>>698 public フィールド
protected フィールド
private フィールド
public メソッド
protected メソッド
private メソッド
>>699 すまぬ。
>>700 今、僕もそうしています
>>701 フィールドとメソッドで分けるの?
結構、private (先頭無指定)から 書いてあるソースを見かけることが多いので、
ほかの人はどうしているのかと思い、質問してしまいました。おじゃましました。
>>695 確かに,-O0で最適化を抑制しているのにvolatileの有無で結果が違
うのは,変数がレジスタに割りつけられている可能性が出てきておか
しいと思います.もう少し検証して何か出たら,また報告します.
>702 そりゃスコープ省略すると勝手にprivateになるからだろw
>>702 分ける。理由は特にない(藁。つか、フィールドとメソッドが一緒だと読みにくいのよね、俺的に。
まぁ趣味だから、どう書くかよりも統一されてるコトの方が重要だと思ってる。
>>704 そうだね。俺、あれが好きじゃないからpublicを頭に回してprivateを明示的に書くようにしてまふ。
これもやっぱし趣味だな。
ちなみに漏れはオブジェクト指向(データ指向)マンセーなので 利用者がスグに知りたいパブリックメンバを前に、 プライベートなメンバは後ろ〜の方に書いてます そもそも外から見られたく(いじられたく)なくてプライベートにしてるのに 真っ先に書いてあるのは不自然じゃないか、と
>>694 > public: ClassName x;
これだとUserの中にproperty<..User..>の中にUserの中にproperty<..User..の中に…
の無限入れ子になってしまう。C++はJavaじゃないので参照なりポインタなりは
そのむねちゃんと書かんといかんよ。
template <typename Type, class ClassName, Type (ClassName::*Getter)(), void (ClassName::*Setter)(Type)>
class property
{
private: Type m_Value;
public: ClassName& x;
public: property& operator= (Type rhs){ (x.*Setter)(rhs); return *this; }
public: operator Type() { return (x.*Getter)(); }
public: property(ClassName& owner) :x(owner){}
};
class User
{
private: int v_;
public: int Get(){ return v_; }
public: void Set(int v){ v_ = v; }
property<int, User, &User::Get, &User::Set> ValueProperty;
public: User() : ValueProperty(*this){}
};
> private: Type m_Value; あとこれは要らんな。
個人的に値とpropertyを分けるのは好きじゃないな property < int, ...> Value; Constructor() : Value(this, 初期値) {} Get(int& value); Set(int& value, int& new_value);
710 :
デフォルトの名無しさん :02/09/09 21:45
ファイルを操作するクラス CFileがあります。 ファイルのパスを格納しているクラス CFilePathがあります。 パスにならってファイルを開く関数 CFilepath::open() を定義して、 CFileをなんらかの形で返したいのですが、どのように返したらいいのでしょうか? 最近CからC++に移ってきたんですが、Cみたいにポインタで返さなくても メモリの大量コピーとかはおこらないんでしょうか?
CFilePathって一般的にはやや無理筋そうなクラスに見えるけど、 なんのためにあるの? むしろ、CFile に getpath() みたいなメンバの方が自然な気が。
あと、 >最近CからC++に移ってきたんですが、Cみたいにポインタで返さなくても >メモリの大量コピーとかはおこらないんでしょうか? 戻り値の話なら、値で戻せばコピーが起きるのは CもC++も同じ。 てーか、そもそも、Cで何らかのオーバヘッドが発生する局面で、 C++だとそれが起きないなんて状況は、まずないね、逆はよくあるけど。
どうも書き方が悪かったようです。ここのパスってのは検索パスです。 CFilePathのコンストラクタで {"/usr/share/hoge","/usr/local/share/hoge"}みたいなのが読み込まれて、 CFilePath.open("fuga.dat") で/usr/share/hoge/fuga.dat,/usr/local/share/hoge/fuga.datの順に存在した物を開くと いうものを作成したいのです。
>>713 CFile を継承して、コンストラクタと open() を定義すれば良いと思うが...。
>>714 そうすると、ファイルを開くたびに検索パスを読み込む方法しか思い浮かばないのです。
C++まだよくわかってないんですが、、
>>715 毎回読む、グローバルに保存しておく、staticメンバに保存しておく、お好きなように。
毎回読む、グローバルに保存は避けたいですね。 staticメンバってのはわからないので、調べてみます。 あと、一応、クラスを返すときはどういうように返すのが一般的かを 教えてください。
やっぱり先にお礼を書いておいて良かった!
>>707 そういえばそうでした、ありがとうございます。
ところで、このプロパティの中身をオブジェクトにして
int val = someObject.Property.memberVariable;
のように書いたときに、 someObject が int に変換できないという趣旨の
エラーが起こるのですが、この時は何が起こっているのでしょうか?
冷静に考えると、プロパティの実体のメンバにアクセスするための
ドット演算子が未定義である為に起こる症状な気がするのですが、
operator. ってオーバーロード出来ないんでしたでしょうか?
こういう場合に自然な振る舞い(C#などのプロパティのような振る舞い)に
する方法は何かありますか?
どなたかよろしくお願いします。
>>709 分けないと、アクセス制限の線引きが曖昧になりませんか?
インスタンスのプロパティなのに、そのインスタンスが受けるアクセス制限が
外と同じというのはちょっと…と思うのですが。
>>718 . :: .* ?はオーバーロードできん。
>>717 CFileに参照回数計測を実装すれば、ポインタ1つのコピー+αくらいで逝けるヨン。
他の場面で多少のオーバーヘッドは出るけど、
CFileみたいなクラスはそんなに速度は要求されないだろうしネ。
って、よくみたら、staticメンバわからんとか逝ってるし。 staticメンバわからんやつに参照回数計測はまだ無理かな。
>>711 もしくは CFile::open(const CFilePath&) を作るか。
>>721 staticメンバだと、pathリストパターンjが複数存在する場合に困るような...
今回の場合、複数ないかも知れんけどね。
プロパティって、対応する実体が無くてもあたかも存在するかのように見せられる
property<int, OwnerClass, &OwnerClass::GetLength, _> length;
int OwnerClass::GetLength() const {
return strlen( m_string_data );
}
のが便利なとこだと思ってるので、常にメンバ変数とペアになってる
ことを仮定したpropertyテンプレートって好かんのだが…。
>>718 class property [with T=SomeValue&] {
T operator()() const { return (x.*Get)(); }
};
と謎の()を定義して、その時だけプロパティらしからぬ
int val = someObject.Property().memberVariable;
で使うか、operator. の代わりに operator-> のオーバーロードで
我慢するしかないような気がする。
725 :
デフォルトの名無しさん :02/09/10 09:23
オペレーターを定義するときには、 メンバー関数にするのとフレンド関数にするのとどちらが良いのでしょうか? それぞれのメリット・デメリットにはどんなことがあるのでしょうか? いろんな立場からのご意見をお聞かせ下さい。
スレ違いかもしれませんが、統一スレのようなので、質問させてください。 みなさんはC++を使う場合のGUIまわりはどうしてます? Winだと、BCBかMFCというところでしょうか? .NETの方がきれいなGUIになっていったらどうします?
727 :
デフォルトの名無しさん :02/09/10 10:56
凄い初歩的な質問で申し訳ないんですが、よろしくお願いします。 Win32コンソール用アプリケーションで、ユーザに1ラインに複数の言葉を入れてもらい、 それを個々のstringとして認識するにはどうしたらいいのでしょうか? 例としては、ユーザがcinに "apple banana orange grape" と入力した場合に、スペースを認識して"apple"というstring、"banana"というstring、 という具合に個別のstringに分けたいのです。 cin >> a >> b >> c; という様な手を使おうと思ったのですが、ユーザが入力する言葉の数は一定してないので、 言葉が3つ以下の時にキチンと作動しません。 お願いします。
すみません、上げてしまいました。;
一度に1lineまるまる拾ってきた後、それを解析 strtok()などのループ
googleでstrtok検索したらなんとなくわかりました。 ありがとうございます。m(_ _)m
ただし、strtok は少し癖があるから、気をつけて。 場合によっては、strtok_r を使うこと。
>>725 それは、すでに語られ尽くしてる気がするな…。
>>734 gcc-3.2を使わない。2.95.x使うの止めた方がイイよ。
>>725 立場がどうの、っつーほどのもんではない。
2項オペレータの左項に当該クラス以外のオブジェクトが来る場合を
許容しようとしたら、必然的に非メンバ関数として定義してやる
しかない、というだけの話。
>>727 せっかく std::string をつかってるなら、文字列を char配列にコピー
してからでないと使えない strtok よりも、string のメソッドになってる
find、find_first_not_of、substr あたりを組み合わせて使ったほうが
よいんでは。
boost::tokenizerは?
739 :
デフォルトの名無しさん :02/09/10 16:18
VC++6っす。 プログラムに埋め込んで使えるようなデータベースライブラリーって ないですか?Oracleとかだと、別途インストールしたりサーバの設定とか 面倒なので。 今まではSTLのmapとvector使ってやってたんだけど、そろそろ面倒で限界。鬱になる。
741 :
デフォルトの名無しさん :02/09/10 16:37
743 :
デフォルトの名無しさん :02/09/10 16:45
744 :
デフォルトの名無しさん :02/09/10 16:46
747 :
デフォルトの名無しさん :02/09/10 17:01
748 :
デフォルトの名無しさん :02/09/10 17:02
>>739 目的を明確に。
データベースといってもいろいろなんだが、何をしたいんだ? リレーショナル
データベースを使いたいのか、オブジェクトのシリアライズをしたいだけなのか、
そのあたりを詰めると話がまったく違ってくる。
C++ のオブジェクトのシリアライズをやってくれるような データベースなんてあるの?
754 :
デフォルトの名無しさん :02/09/11 00:29
例えば array< T > みたいなテンプレートがあって、これを容易に vector や list に差し替える方法ってある? イメージ的には template <class T> typedef std::vector array; みたいな。
>>753 あるらしい。昔、エピステーメーが書いてた本で読んだ覚えがある。
(その本、捨てちゃったけど)
>>754 明らかにムダなので、ないと思われ。
template< template<class> class Container, class T > … Container<T>
>>755 vector と list 差し替えるって話はムダだが、template を typedef したいっつー
のはあり得る話か。
ちなみに、それは無い。ただし template パラメタに template を渡す、たとえば
template <template <typename T> class Prod>
class Order {
Prod<int> prod_;
...
};
みたいな書き方は出来るから、目的は達成できると思う。
>>757 g++ とかなら、
template< template<class> class C, class T > void foo( const C<T>& array ) {
for ( typename C<T>::const_iterator i = array.begin(); i != array.end(); ++i ) {
cout << *i << endl;
}
}
vector<int> v;
foo(v);
list<float> l;
foo(l);
みたいな書き方はできるけど。
>>758 template template parameter ね。ただ typedef template は、なぜか ANSI C++
の規格には存在しない。
(次期 ANSI C++ の規格に入る最右翼だとは思うけど)
objectstore?
いろいろなレスを頂きありがとうございます。 シリアライズできるデータベースがあるなんて知りませんでした。 今回探しているものは、リレーショナルのほうですが そちらにも興味があります。 よろしければ名前など教えてください。
763 :
一週間ぶり :02/09/11 12:01
こんにちわ。
enumのシンボル(?)って全部大文字じゃマクロと被って紛らわしいすかね? enum { AHYA, UHYA }; みたいなの...
>>764 個人的には大文字を打つのがめんどくさい
>>764 定数であることを明記するため、俺は大文字にしてるけどな。
#define AHYA 0
これと enum { AHYA = 0 }; は同じようなもんだろ?
>>764 良いエディタを使え。
typedef templatesの代わりに#defineで何とかするとどれくらい残念?
768 :
デフォルトの名無しさん :02/09/12 00:34
age
>>727 おそレスだがstrstremとか使っちゃダメなのかい?
作ってみた。 string s("apple banana orange grape"); istrstream ss(s.c_str()); string tmp; while (ss >> tmp) { cout << "data = " << tmp << endl; }
#define AHO 0 と enum { AHO=0 }; が同じなんですね。
774 :
デフォルトの名無しさん :02/09/12 01:47
クラスのプライベートなメンバ変数を返すパブリックな関数で int GetValue() { return a; } と const int& GetValue() { return a; } って同じ事ですか? 肥大化しちゃった(std::vectorとかの)オブジェクトを参照したい時に 下の方が良いかなーとか思ったのですが、実際の所どうなんでしょう? 上のやり方だとオブジェクトの実体をまるごとコピーしてるように思えるんですけど 認識間違っていますか?
>775 なるほどありがとうございます ということは、追加で質問なのですが class cA { public: const std::string& GetSTR() { return str; } private: std::string str; } int main() { cA a; std::string b; b = a.GetSTR(); b.append("test"); return 0; } というのは安全なコードでしょうか?
あー・・・コンストラクタ書いて無いとかいうのは別として・・・
>>776 b = a.GetSTR();
でbにコピーされるんじゃ?ちなみに、
a.GetSTR().append("test");
は通らない(はず)。
>>778 コピーされなきゃまずいだろ。
constにはappendできないのだから。
あれ・・・ std::string* b; b = a.GetSTR(); b->append("test"); かな・・・ すみません、混乱してます
>>776 GetSTR()はconstであるべきだが、それ以外は別にいいんじゃないの。
あーごめんなさい appendじゃなくて、例えばfindとかの話でした。 プライベートに持ってるstd::mapのキーを std::setに列挙して返すような場合です。
>>782 それなら、直に〜.find(a.GetSTR())してもいいし、
const std::string& b = a.GetSTR();
〜.find (b)
としてもいい。
何か混乱してません?
>>774 落ち着いて考えてみそ。
上手く伝わっていなかったようです 修正版コード class cA { public: const std::map<string, int>& GetMap() { return mymap; } private: std::map<string, int> mymap; } int main() { cA a; const map<string, int>& b; b = a.GetMap(); if (b.find("test")) cout << "OK" << endl; return 0; } こんな感じです >783氏からちょっとヒントを得ました が、ここまで書いてふと気が付いたんですが こんな実装必要ないみたいでした・・・ 長々と失礼しました
const map<string, int>& b; b = a.GetMap(); これは許されないぞ
あ、はい。わかります。 ごめんなさい。
>>773 (´-`)。o ( ……これだけを見ると、ぜんぜん違うと突っ込みたくなるなぁ……)
789 :
デフォルトの名無しさん :02/09/12 11:12
>>786 これって、constじゃなきゃいいの?
「&」ってやってるのがまずい?
漏れならcAのメンバ関数にint find(string )って入れて済ますけど
嫉妬期待。
>>789 参照は宣言時に初期化されなければならない。
791 :
デフォルトの名無しさん :02/09/12 12:45
コンストラクタ中で、外部の関数に this を 渡すとまずいですか?
コンストラクタから出る前に、問題の関数がthisの先を見ないなら 問題は無い。例えば class Bar; class Foo { Bar *m_ptr; public: explicit Foo(Bar *ptr) : m_ptr(ptr) {} }; class Bar { Foo m_foo; public: Bar() : m_foo(this) {}, }; はOKだけど、Foo(Bar *)がptr->xxを含んでいたらアウト。 ただし、Barの基底クラスの非仮想関数を呼ぶ場合は、少なくとも普通の 処理系なら正常に動くはず。
>>792 レスありがとう。
ルール上はアウトなんですね。
794 :
デフォルトの名無しさん :02/09/12 13:48
便乗 VC6だと 警告 Bar() : m_foo(this) {} OK Bar() { m_foo = this;} となるんですが、上の書き方は言語規約上OKなのでしょうか。 auto_ptr<Foo>とかで、オーナーポインタ渡すだけの為に auto_ptrのディフォルトコンストラクタが走るのは気持ち悪いっす。
どんな警告?
>>795 warning C4355: 'this' : ベース メンバ初期化リストで使用されました。
非静的メンバ関数の中でのみ有効な this ポインタが基本クラスの
初期化リストで使用されました。
Microsoft の拡張機能を有効にするオプション (/Ze) を付けて
コンパイルした場合はレベル 1、それ以外ではレベル 4 の警告となります。
よく考えたら、この構文通らないと、オブジェクトを直持ちした場合
構築できないじゃん。
そんなんでいいのか C++
だから、コンストラクタ内で渡した先が そのthisの中身にアクセスしなければ合法だって言ってるじゃん
あぶない使い方になる可能性もあるから警告出たって良いんじゃない? というか、直持ちした上で他のオブジェクトに依存するような設計が悪い。
すいません、お尋ねします。 浮動小数点数のscientific表記(0.02e+12とか)が何を意味しているか わかりません。解説ページご存知でしたら教えてください。
>0.02e+12 ワラタ
801 :
デフォルトの名無しさん :02/09/12 16:25
基本的には、ものすご〜く大きな数か、ものすご〜く小さな数を表していると思われ。
>>800 Σ(゚Д゚;)
・゚・(ノД`)・゚・イッショウケンメイカイタノニ
>>801 ありがとです。
詳細な説明があるサイト知りませんでしょうか。
>>799 すまぬ、勘違いしてた
仮数部・指数部
0.02e+12
だと、仮数部 0.02、指数部 12 = 200000000 ぐらいか?(0適当)
勘違いは、仮数部・指数部が逆だと思ってた
(´-`).。oO(800ゲットにうかれてたんだろうな…)
あっでも普通は 0.2e+11 になるから「プ」ぐらいならいいのか ん、2.0e+10 か? 処理系によるのか?
805 :
デフォルトの名無しさん :02/09/12 18:26
まぁ、どうでもいいんだけど、 0.02e+12なる表記が出てくることってあるの? そもそも、こういう表記って表記の定義としては正しいの?
806 :
デフォルトの名無しさん :02/09/12 18:26
0.02e+12=0.02×10^12 2e10 って書いても同じ
例えをそんなに問い詰められても・・・ わかんないから聞いたのに・゚・(ノД`)・゚・
Ae±B=A×10^±B
0.00001 って長く書くよりは、 1.0e-5 って書いた方が桁数がわかりやすい
799はいじめられっこ
0.02e+12を笑うやつが2.0e+10とかいうのか?
有効桁数を問題にしたいときは 0.02e+12 とか出てくるかも。 あと、5.2e+10 と 4.8e+11 を比べるより 0.052e+12 と 0.480e+12 のほうが解りやすいとか。
800もいじめられっこ
815 :
デフォルトの名無しさん :02/09/12 20:06
便乗で質問です。 C++のcoutでfloatなんかの数字を表示するとき、 4.8e-3 みたいな表示を禁止して、常に 0.0048…みたいな表示にするのにはどうしたらよいのでしょうか? あと表示の有効桁数を指定することも出来るのでしょうか?
>>815 指数表示をやめる・・・・・fixed
有効桁数・・・・・precision(n)
817 :
デフォルトの名無しさん :02/09/12 21:48
>816 Thanx!できましたよ。
818 :
デフォルトの名無しさん :02/09/12 22:00
ところで、 cout.setf(ios::fixed); cout.precision(8); みたいに変更した後、設定をデフォルトに戻したい場合はどうすれば宜しいのですか?
>>818 cout.unsetf(ios::fixed | ios::scientific);
cout.precision(6);
precisionは返り値として元の精度を返すので、それを保存しておいて
あとでprecisionに与えてもよい。
while( cin >> no >> ma >> en ){ students.push_back( Student(no, ma, en)); } こういうコードよく見るけど(マ板からの引用)、 たとえば、noの入力が失敗した場合、 続く「cin >>ma >> en」(ただし、cinはfailになってる)は 問題ないの? 俺のg++では、どこで入力に失敗しても、 変な動作を引き起こさずにすんなりwhileを抜けてくれるんだけど、 それは標準で保証されてることなのかな? 誰か知ってたら教えて。
>>820 cin >> no >> ma >> en は
((cin.operator>>(no)).operator>>(ma)).operator>>(en)と同じに
なると思うから、cinが失敗した所でoperator>>が働かなくなる
ようにされているのでは?
>>821 レスありがとうございます。
そうですね。それで、疑問なのは、
cinがすでにfailになっている場合、
cin >> x;
は、「何もせずにcinを戻す」のか、
何かするのか、あるいは、本当は
未定義なのかということなのです。
すみません。
823 :
デフォルトの名無しさん :02/09/13 00:40
>819 Thanx!早速試してみたいと思います。
>>822 cin.fail()がtrueの時、cin.clear()を行うまで、ストリームの処理を行わないこと
が保証されているようです(C++標準ライブラリP573)
見事にcinがスキップされるね。(gcc3.2) #include <iostream> int main() { int i; std::cin.setstate(std::ios::failbit); std::cin >> i; }
>>825 例外を投げて欲しければ
iostate exceptions(iostate except);
でマスク外さないと。
vectorって自己参照ポインタって使えないんですか? VC5.0ではじかれますた こんなかんじ class foo{ ・・・ foo* pParent; vector<foo*> pChild; ・・・ }; できないのでfoo** pChildにしますたが・・・ (メモリ管理自力(泣めんどくさい怒))
829 :
デフォルトの名無しさん :02/09/13 22:19
ageてみつ
vector<class foo*>?
>>828 それに何の問題が??
参考までに、
#include <vector>
using namespace std;
class foo{
foo* pParent;
vector<foo*> pChild;
};
int main(){ return 0; }
は、VC6、BCCで通りますた。
bcc5.5.1で通りますた。
もしかして、thisをpChild.insert()するとか? それは何故か知らんが、VC6だったら vector<foo> pChild; で通るかと。
と思ったら違った。。。
using namespace を何も指定されていない状態に戻すには?
ない
{ using namespace hoge; // 有効 } // 無効
class foo { protected: type obj; foo* p; public: hoge(){p->obj=something;}<−−−−−−* }; *って外部からobjを操作してることになるんですか? VC5.0だと通りますたが・・・ちょっと不安
objって何
>>840 obj:何らかの型のオブジェクトです
hoge()の呼び出し元インスタンスと違うインスタンスのpを介して
protectedにアクセスできるのか?ということです
この日本語だと外部アクセスな気がしますが・・・
んで、VC5.0だと通っちゃうんですよ(動作も意図したとおり)
あーそういうことか。 アクセス保護はクラス間の約束でしかない。 以上。
844 :
デフォルトの名無しさん :02/09/14 17:01
質問です。クラスの static メンバ変数のデストラクタが呼ばれないのですが、 何かいい方法はないでしょうか?volatile をつけても駄目でした。 コンストラクタで OS からリソースを確保するクラスは static メンバ変数にしては駄目なのでしょうか? 以下は確かめに使ったソースです。 #include <iostream> class A{ public: A(){std::cout << "A()\n";} public: ~A(){std::cout << "~A()\n";} }; class B{ public: static A ainst; }; A B::ainst; //<- コンストラクタだけでデストラクタが呼ばれない void fun(){ static A a; //<- これはちゃんと呼ばれる } void main(){ fun(); } よろしくお願いします。
グローバルで A B::ainst; じゃない
>>843 同じクラスのインスタンスのprivateメンバに触れないんじゃ
コピーコンストラクタなんて書くとき困っちゃうよね。
ごめん迂闊だった グローバルでやってるね これでいいはずだと思ったけど・・・
デストラクタ走るのが main() のあとだからじゃないかな。そのタイミングだと cout が生きてるかどうかも分からないし。
main()のリターンのあと? 処理系依存っておちはない?
レスありがとうございます
>>845 ちなみにただのグローバル変数にした時も同じになります。
>>848 c関数 atexit() で、出来る限り最後までやってみたのですが、
main() のはじめに atexit() した関数が呼ばれたのが
上記例の fun() 内部の a のデストラクタ呼出し後で、
ここまでは確認できたのですが…
もしスタートアップルーチンが、コンストラクトとデストラクトを
逆の順番にやってくれているとすれば(希望的観測)、
コンストラクタでは std::cout が生きていて
デストラクタで生きていないっていう事は無いような気がするのですが…
デストラクタで適当にファイル作って、呼出されてるかどうか 試してみては。
ぎゃふん!
>>848 さんの言っている事が正しかったです。
std::cout が破壊された後でした。
printf で同じ事を書いたら、ちゃんと呼ばれている事が確認できました。
お騒がせしました。ありがとうございあした。
そうすると外部変数ってのはmain()始まる前に確保して 終わった後に解放するの?プロセスレジスタ(?名前忘れた)は main()の前からプログラムに入ってるって事?
>>852 main()から始まるわけではないんですね
なんかだまされた気分
_cdeclとか_pascalとか関係ない?
>>849 C/C++ のプログラムは(通常は)スタートアップルーチンっていう
ものがリンカによって付加されてますよん。
>844 調べてきまつ
スタックポインタの初期化 グローバルポインタの初期化 ROM to RAM コピールーチン data 領域のコピー bss 領域のゼロクリア main 関数へのジャンプ よーなことやってるんですか初めて知りましつ
FAQかもしれないけど、ウィンドウ(生成・破棄)のクラス化に関する質問です 要はウィンドウプロシージャがうまくクラス内に収まらないという話なのですが staticで修飾しちゃうとメンバにアクセスできないし CALLBACKじゃなくしてパブリックメンバにして、CALLBACKの方から呼んでやるっていうのも ラッパークラス自体グローバルにしなきゃいけないし、そもそも隠蔽しきれてないし・・・ 何かウマイ方法は無いもんでしょうか?
ATLのソースを見る
thisをHWNDに埋め込む。
彼女の膣に鰯を突っ込む
鰯→鮪
メンバに別のクラスのポインタを持つクラスを作ったとして 別のクラスのポインタが無効になったら自滅するように出来ますか? 例えばこんな風にして class A { }; class B { A* child; public: B(A* a) { child = a; } }; A* testA = new A; B* testB = new B(testA); Aのデストラクタが呼ばれたらBも一緒に死んでいくような・・・
>>864 できない。Observer/Obsavable パターン使え。
AにReference Counterとフラグ付けて、デストラクタの代わりに A::Releaseをよびだして、そこでフラグをたて、RefCountをへらして、 Bの方では適当にフラグをポーリングすればええんでないかい?
867 :
デフォルトの名無しさん :02/09/14 20:55
自作クラス用フレンド演算子 std::ostream& operator<< (std::ostream& lhs, const myClass& rhs) を定義した時、これが呼ばれてほしくない場面で呼ばれてしまいます。 通常は myClass myClassInstance; std::cout << myClassInstance; を想定していて、これはうまく動くのですが、インスタンスの存在するアドレスを確認したくて std::cout << &myClassInstance; と書いた場合まで、上の演算子が呼ばれます。 operator& () はオーバーライドしてないし、したくありません。 これは operator<<(std::ostream& lhs, myClass rhs); にする以外でうまく解決する方法はあるでしょうか?
コンパイラ変えてみたら
>>867 std::ostream& operator<< (std::ostream& lhs, const myClass* rhs)
を作るとか。
PCだったら少なくとも3つのコンパイラは入れるよ。
>>870 includeとかlibみたいな環境変数がコンフリクトしてマズーなことになったりしない?
っていうか今時そんな環境変数でディレクトリ与えるのはもしかして主流じゃない?
環境変数はMSに遠慮してどこも使わなくなったね
>>872 BCCは-Iとかでディレクトリを与えてたな。gccはどうなってるの?
>>873 bccもgccも設定用ファイルがあるよ
MSは自社製品でconfrict起こすからな<環境変数
mapのデータに関数ポインタ渡してキーに関数名入れて呼ぶと楽しいよ
>>873 引数で -I, -L を使って渡すか specs という設定ファイルに書いておく。
bcc で使ってる bcc32.cfg の高機能版みたいなもんだ。
>>874 >>877 サンクスです。
じゃ、VC++/bcc/gccの混在も十分可能なのか。どうしよっかな〜。
iniファイル管理クラスを自作していてつまづいちゃったんですが iniファイルみたいな3層構造([section]->key->value)を うまく管理するにはどうしたらいいんでしょうか? stlのmapにmap持たせようとしたり、色々やってみたんですが 僕の脳味噌じゃちょっと無理みたいです... 要件としては、iniファイルの内容を何らかのカタチでメモリ上に保持して 「[section]->key」でアクセスすると「value」が返ってくる様なモノです もっと言っちゃうとVCLのTIniFileみたいなモノです 皆さんのお知恵をお借りしたいです (「BCB買え」とかは無しでお願いします...)
>880 うー...頑張ります ところでこれはCの質問だと思うんですが、ついでにお願いします char temp[] = "aaaa\0bbbb\0cccc\0dddd\0\0"; という文字列があったとして、aaaaから順番に取り出していきたい場合 std::map< std::string, std::string > mymap; while( 0 < strlen( temp ) ) { // \0\0 が 0 であることを期待して mymap[temp].insert("test"); // std::stringが\0までを文字列と扱ってくれると期待して temp = strchr(temp, '\0') + 1; // 最初の\0までを削除したい } で期待通りの動作をしてくれるでしょうか? ちょっとwhileが絡んでくると、怖くてテストランできない...
>>879 COMPOSITE にすれば?
ini ファイルというよりレジストリになるからちょっとオーバースペックか?
直前の話題とかぶるけど、なんで MS は VC の設定にレジストリ使わないんだろう?
レジストリは階層構造つきの環境変数的な意味合いじゃなかったんだろうか?
他社への嫌がらせなのかな?
>882 それってデザインパターンですよね 日曜PGなので理解が浅いですが、実装できるか頑張ってみます そりゃそうと>881じゃコンパイル通らないですね... ちょっと長いですけど実コードから抜粋 メンバ変数 std::map< std::string, std::map< std::string, std::string > > Entry; に、Entry[section][key] = value の形でデータを収めたい コードは次レス(入りきらなかった...) パッと見ておかしなところがあったら教えて下さい よろしくお願いします
char* SecTemp = (char*)calloc(sizeof(char), 2048); DWORD hRetSec = GetPrivateProfileSectionNames(SecTemp, sizeof(SecTemp), FilePath.c_str()); if (hRetSec > 0) { char* KeyTemp = (char*)calloc(sizeof(char), 2048); while(0 < strlen(SecTemp)) { DWORD hRetKey = GetPrivateProfileSection(SecTemp, KeyTemp, sizeof(KeyTemp), FilePath.c_str()); if (hRetKey > 0) { char* key = (char*)calloc(sizeof(char), 128); char* value = (char*)calloc(sizeof(char), 128); while (0 < strlen(KeyTemp)) { strncpy(key, KeyTemp, strcspn(KeyTemp, "=")); // "AA=aa\0BB=bb\0CC=..."の"AA"にあたる部分を取り出す KeyTemp = (strchr(KeyTemp, '=')+1); // "AA="の部分を削除(前詰め) strcpy(value, KeyTemp); // "aa\0BB=bb\0CC=..."の"aa"にあたる部分を取り出す Entry[SecTemp][key] = value; KeyTemp = (strchr(KeyTemp, '\0')+1); // 最初の\0までを削除(前詰め) } free(key); free(value); } SecTemp = (strchr(SecTemp, '\0')+1); // 最初の\0までを削除(前詰め) } free(KeyTemp); } free(SecTemp);
> パッと見ておかしなところ 3行目以降見てないけど… > char* SecTemp = (char*)calloc(sizeof(char), 2048); > DWORD hRetSec = GetPrivateProfileSectionNames(SecTemp, sizeof(SecTemp), sizeof はいやん。
リークし捲りなので、std::stringを使おう。
> DWORD hRetSec = GetPrivateProfileSectionNames(SecTemp, sizeof(SecTemp), は DWORD hRetSec = GetPrivateProfileSectionNames(SecTemp, sizeof(*SecTemp), ~~ でした... (char*)calloc(sizeof(char), 2048); はマズイですか? callocって「バイト数*長さ」で領域確保するんだと思ってましたがどうなんでしょう?
あと>886は無理じゃないですか? GetPrivateProfileSectionNames関数にstd::string渡せないし 実体渡ししたとして、その挙動(ポイント先の確からしさ)は保証されてないし
>888 × 実体渡し ○ 直アクセスでポインタ渡し
char* SecTemp; なら、 sizeof(SecTemp) -> 4 sizeof(*SecTemp) -> 1
あそうか、ポインタがポインタ持ってるんだから sizeof(**SecTemp)か......な? 全然理解が足りてないですね僕...
>>888 そういうときはフツーstd::vector<char>を使う。
char t[1024]のときtの型はchar[1024]で、sizeof(t)は1024 char *pなら、pの型はchar*, (*p)の型はchar、 (**p)はエラー。 sizeofで要素数が分かるのは配列(と構造体)のときだけ。 ポインタの要素数はsizeofではわからない。
>893 理解しました... では char* SecTemp = (char*)calloc(sizeof(char), 2048); なら (sizeof(char)*2048); が正解ですか? >892 でもstlのコンテナ群って、自分のインターフェース以外が内容を書き換えちゃった場合 その後の挙動は保証されてないですよね?
sizeof(char)は常に1だから、普通は単に2048とする。 (普通、はdefineとか使うんだろうが。笑い)
>>894 vector<T> (T != bool) の内部データはTの配列として使えることが保証されてる。
> (sizeof(char)*2048);
正解。…だが、 sizeof(char) は常に1なので単に2048でも可。
あと意味的には calloc( 2048, sizeof(char) ); が正しいのではなかろうか。
恥かいたけど1つ(2つ)賢くなりました ありがとう
文字ベースのC++の(簡単な)入門が終わりました。 これからBCBでGUIなんかやりたいのですが、 よい参考書を教えていただけないでしょうか。
>>898 Delphiの参考書ならなんでも可。
Object Pascal->C++の手動コンバートはなかなか面白いよ。
>>896 > vector<T> (T != bool) の内部データはTの配列として使えることが保証されてる。
ソースきぼん。以前、別所でその問題について議論されてたのを
思い出した。
More Exceptional C++ の48ページによると > This was fixed in 2001 as part of Technical Corrigendum #1 to > the C++ standard, which now requires that the contents of > a vector are stored contiguously, just like an array とな。いや、俺もTC1の現物は見たこと無いんだけど。
>>900 Effective STL に書いてある。
ANSI C++ の規格書には記述がないんだが、後で採択された amendament に
書いてあるそうだ。(俺は確認してない)
903 :
デフォルトの名無しさん :02/09/15 21:10
デバッグすると,ある変数の値に-1.#IND000000000と入っていたのですが,これは何を意味するのでしょうか? (INFなら無限大なのは知っています) よろしくお願い致します
>>899 マジすか?Pascalなんてわかりません。(涙
知りたいのは、GUIまわり(コンポーネントって言うんですか)なので、
Pascalわからないでもよかったりします?
905 :
デフォルトの名無しさん :02/09/15 21:27
906 :
デフォルトの名無しさん :02/09/15 21:28
>>904 899です。
俺もDelphiは全くやる気はないけど、何せBCBのいい参考書が全然ない
ですからね。VCL部分は全くと言っていいほど共通なので、必ず役に立ち
ますよ。
ただ、C++には独自の関数を多数備えているので、VCLでできる事でも
C++でやった方が良い場合もいくつかあります。
Object PascalとC++間のコンバートには一種の規則のようなものがあり
ますが、それをうまくまとめたHPをまだ知りません。実際に試してみられ
るのが一番の近道です。
俺はここでよく質問しています。
「C Builder相談室 Part3」
http://pc3.2ch.net/test/read.cgi/tech/1016065855/
コンストラクタで例外投げてくる可能性がある関数を呼ぶのってマズいですよね・・・ インスタンス生成時に1回だけしか呼んで欲しくない処理を実装したいんですけど 何かウマイ方法はないですか? それとも複数回呼ばれた場合の処理を盛り込んだ方が賢いですか?
> コンストラクタで例外投げてくる可能性がある関数を呼ぶのってマズいですよね・・・ 何故? それがインスタンス生成に絶対欠かせない関数呼び出しなら、 失敗して例外を投げた時はコンストラクタも失敗とするべきだし、 上手く呼び出せなくても何とかなる関数なら、コンストラクタの中で try - catch で適切に対処すればよいだけ。
>910 もし例外が起こりうる関数より下でnewとかしてた場合 デストラクタで無効なdeleteしちゃったり 最悪デストラクタが呼ばれない(コンストラクタが完走していないので) とかいう事になっちゃいませんか?
>>911 Effective C++ とか読んだ方が良いかもしれんな。コンストラクタ中で例外が
発生した場合には、対応するデストラクタは呼ばれないことが保証されている。
したがって、コンストラクタ中で後始末が必要な操作をする場合には
1. コンストラクタ内に try - catch を書いて後始末
catch した後で throw; で例外をさらに外に投げる
2. メンバ変数やローカル変数としてスマートポインタを使う
いずれかで攻める。
なるほど ありがとうございました
>>907 >>908 ありがとうございました。だいぶわかってきました。
(それにしても、BCBは不人気なのかと心配になってきました。)
>>914 BCBが不人気というよりも、Delphiの出来が良すぎて皆そちらに流れて
しまうからでしょう。
もしくはC++使いはVisual C++(.NET)に流れてしまいます。結果として
BCBユーザーは少なくなってしまっているのかもしれません。
VCLはObject Pascalで書かれているので、C++との相性に今一つ難が
あるような気がします。しかし、それでも無理矢理にでも他言語に介入
できるのはC++の大きな強みだと思います。
BCBに慣れたら、Visual C++(.NET)への移行もできます。でもVCLが
便利なので、MFCが嫌になるでしょうけど。
横から便乗質問。
俺は半分趣味のMFCプログラマ(全然人気のないシェアとか書いてる)
なんだけど、.NETになって迷ってる。(プロじゃないのに質問すまん。)
MFCのサポートは打ち切りらしいし、マネジッドでC#もどきをするなら、
いっそC#の方がいいのかとも思うし。
でも、C++は好きで(なじんでて)捨てるつもり気にはなれない。
結局、Builderに行こうかなあとも思うんだけど、いまいちマイナー感が。
やっぱり、参考書籍の少なさや、Delのおまけって感じが少し不安。
でも
>>915 なんか見ると、やっぱ、BCBでいいのかとも思うし。
VC++/MFC屋の人は、どうするつもり?
>>916 > MFCのサポートは打ち切りらしいし、
VC++.net には新バージョンの MFC 入ってるけど。
マクロやら関数宣言やらよく使うインスタンスにextren つけたりしている.hファイルをほぼ全ての.cppでインクルードするのは 何かまずいことがありますか? あ、他の.hファイルでインクルードする時は #define HOGE #include "hoge_def.h" #undef HOGE で"hoge_def.h"側でHOGEが定義されてたらexternを避けるとしてます
>919 逆でしょ 共通ヘッダファイルに #ifndef ___hoge_def #define ___hoge_def (内容を適当に) #endif // ___hoge_def としておけば、多重定義にならない
>>919 「ほぼ全ての.cppでインクルード」っては、ヤだな。
機能ごとに別ファイルに分類して、必要なものだけを
インクルードすべきじゃないのか。
922 :
デフォルトの名無しさん :02/09/16 10:30
乱数を均等に作るにはどうすればいいですか? 3600の内、1〜15を当たりにすると1/240に収束するのに 7200の内、1〜30を当たりにすると1/280に収束します。なぜ?
疑似乱数生成器は何使ってるの?
>>922 好みのテーブルを作れ
つか、均等に(等間隔で)出てきたらそれはすでに乱数ではない
925 :
デフォルトの名無しさん :02/09/16 10:55
例えばRAND_MAXが32767だったら 3600で割った余りは1〜367が選ばれやすいから 均等でなくなるってことですか?
>>925 そう。単純にはその余りの部分が出たら捨てるといい。
927 :
デフォルトの名無しさん :02/09/16 11:07
クジを32768本にして当たりを136本にしたら ちゃんと1/240に収束するようになりました。 もっとスマートな解決法があればよかったのですが・・・ なにぶん初心者なもので。
根が深い問題だからスマートな解決法はないと思ったほうがいいよ
一番スマートなのは剰余から除算に変えること。 ただ、整数で演算を行うと誤差が出てくる。
余りがその誤差に転化しただけでは?
>>930 剰余は乱数の性質を変化させるけど、
除算は乱数の性質を変化させない。
除算後に表現できる数値の範囲で精度が保たれる。
>>930 乱数ジェネレータの種類によるけどね。
普通の実装は剰余法だから、普通は931の言うことは正しい。
933 :
デフォルトの名無しさん :02/09/16 11:32
インラインメンバ関数を、実装をクラス宣言と一緒じゃなくて別に書く場合、 "inline"キーワードは宣言と実装のどっちに書くのが正しいんですか? どっちに書いてもVCとBCCではOKみたいだけど、ちょっと気になるので。
オブジェクト指向ってなんぞや?
なにが?
>>935 試したソースを出せ。
何か勘違いしてるだろおまえ
>>933 どっちに書いてもOKじゃなくて、
どっちに書いても無視される。
どっちでもいいはず。 漏れは実装側に inline を書きます。inline の無い実装が ヘッダにあると気持ち悪いので。
>>939 実装にinlineを書くと同じコンパイル単位にある関数にしか展開されないはず
除算によって・・・って具体的にどんなコードになるの? わかってる人(プ)書いてみてよ
943 :
デフォルトの名無しさん :02/09/16 11:52
inlineて#defineと同じじゃなかった? コンパイラから見えないと、展開できなかったと思ふ アクセサなんかは .h に入れないと意味ナイト
>>941 inline を宣言側と実装側に書いた場合とで振る舞いが変わってくるという
ことでなのしょうか。どちらの場合でも実装は .h ファイルに書きますよね。
>>942 バーカ。お前なんかに見せてやんねーよ!
素人は除算で十分。
>>942 rand() / (RAND_MAX / double(max));
rand() * (1.0 / RAND_MAX) * max;
普通に↑じゃないのか?
>>945 その除算を知りたがっているのでは
と、マジレスしてみるテスト。
すみません、ageてしまいました。
>>944 いや、
>>941 さんは .cpp で inline 宣言するケースを言ってるのだと
.h で宣言とは別に inline にするのならばどちらも一緒
>inline の無い実装が ヘッダにあると気持ち悪いので。 の補足ですが、ヘッダファイルで class T { inline void foo(); }; void T::foo() {} が気持ち悪いので class T { void foo(); }; inline void T::foo() {} としているという意味です。
すまん、混乱してきた。 .h --------------------------------------------- class T { int get0() { return 0; } // インライン展開される int get1(); inline int get2(); int get3(); }; inline int get1() { return 1; } // インライン展開される int get2() { return 2; } // インライン展開される .cpp ------------------------------------------------ inline T::get3() { return 2; } // このファイル内だけでインライン展開される で、get1かget2かって話?
>>920 本題から外れるが、_ から始まる識別子は処理系が使うから避けた方が良い。
以前に、それでハマったことがある。
(それ以降は UUID 入れるようにした)
>950 処理系が予約してるのって「__〜」(アンダスコア2個)までじゃなかったでしたっけ? だからあえて3個にしてるんですけど、実際どうなんでしょう
規格書には、「_ で始まる名前はグローバルな名前空間 (と ::std) で 使うために予約されている」 とある。 あと、「__ を含む名前、または _[A-Z] で始まる名前は、任意の用途で 使うために予約されている」とも書いてある。
>>951 それはC++で予約されてる名前だろ
_から始まる名前(2つ、3つ連続している物も含む)はC言語の頃から予約されてた
んで、C++になって明示的に_2つが予約されて、C言語用のキーワードと差別化が
計られた。
_3つ以上が予約されているのは現在も変わらず。
WyvernでMP3聞きながらコンパイルしてる漏れは逝ってヨシですか?
>>954 漏れも昔よくやってた。Pentium/120MHzのノートでな(w
double d; __asm { movq d, mm0 emms } cout<<d<<endl;
957 :
デフォルトの名無しさん :02/09/17 23:22
VBのVariant型変数と同じように扱えるC++のクラスってどっかに落ちてないかな。
Win32SDKのVALIANT使え。
>>957 boost::any とか。c++なので当たり前だがキャストが
色々要ってVariantよりは面倒だけど。
960 :
デフォルトの名無しさん :02/09/17 23:55
CからC++への差分だけを学習させてくれ
せめてクラスは全部objectだったら良かったのにね。
962 :
デフォルトの名無しさん :02/09/18 00:20
conservation
すべての親がvoidオブジェクトと考えるのはどうだ。
>>963 でvoidオブジェクトはどのようにして扱う?
>>960 柏原正三「標準C++の基礎知識」(ASCII)
っつー本で俺は学んだが。ちょうどC++を学びたいCプログラマ向け。
>>963 ということにしたいのですね :-)
…はともかく、void じゃなくて void* だよな。
全てはストラウストラープ氏の碁石のままん
(´д`)ママン・・・
いまさら文法の不備を指摘したところでもう手遅れ。
>>966 publish()メソッドで本を出版します
http://pc3.2ch.net/test/read.cgi/tech/1028553308/ でややすれ違いを指摘されたので、、こちらで。
>374 名前:デフォルトの名無しさん sage 投稿日:2002/09/18(水) 03:03
>オブジェクトを直接宣言する場合と、
> CTest oObj(Hoge);
>一旦ポインタの形で宣言しnewする場合は、
> CTest* pObj;
> pObj = new CTest(Hoge);
>どのように使い分ければいいのでしょうか?
>
>375 名前:デフォルトの名無しさん sage 投稿日:2002/09/18(水) 03:10
>スコープを外れても残したい時はnew。
>きっとここよりC++スレ向きの質問。
staticのようなイメージで捕らえればよいでしょうか?
Cで、autoな配列(int hoge[10]を使うべきか、 malooc(int *p=malloc(10*sizeof(int));)を使うべきかは 割と簡単に分かるとおもう。ぶっちゃけると、前者が CTest oObj(Hoge)で、後者がnew CTest(Hoge)。
>972 おおよそのイメージがつかめました。 これからMDIのソースを見て勉強します。 どうも有り難う。
>>973 あれでわかるなんてすごいな。
> Cで、autoな配列(int hoge[10]を使うべきか、
> malooc(int *p=malloc(10*sizeof(int));)を使うべきかは
> 割と簡単に分かるとおもう。ぶっちゃけると、前者が
割と簡単にわかるというけど、これ難しいと思うんだけど。
>974 スタックに置かれるか、ヒープに置かれるか、 その辺の違いだと判断しました。
そーかー、漏れはCでポインタバリバリのあとにC++に逝ったからなぁ。 今では危ない仮定なのかな?
977 :
デフォルトの名無しさん :02/09/18 10:11
コンパイラ実装に関する質問です。 テンプレート関数なキャスト演算子を定義したテンプレートクラスの実体を使ったとき、 VC6だとコンパイルは通るのですが、実行時にプログラム自身が落ちてしまいます。 BCC だとちゃんと対応する型に変換できるのですが、 これは VC が馬鹿なのか、BCC が融通を利かせすぎなのか、私の書き方が間違っているのか どれなのかわかりません。この動作は標準では許容されるのでしょうか? template<typename T> class TemplateClassX{ private: T val_; public: template <class U>operator U(){ std::cout << typeid(U).name(); return val_; } }; void main(){ TemplateClassX<int> i = 10; // ここはそういうコンストラクタがあると思ってください。 long l = i; // vc6 だとプログラムが落ちます、bcc ではちゃんとキャスト演算子が展開されるようです。 }
>>977 特におかしい所があるとは思えん。
コンストラクタが間違っているのか、あるいは
VCのtypeid(long)が壊れているか、だろうな。
>>966 Hoge *が指すのはHogeかそのサブクラスである。
ならばvoid *が差すのはvoidかそのサブクラスであるとするのが良い。
という事でないかと。
>>977 > std::cout << typeid(U).name();
この行を削っても落ちるね。
VC はメンバ関数テンプレートの展開が甘いんじゃないかな。
>>960 差分「だけ」というが、C++ - C >>>> C という罠
>>979 void*はvoidのポインタではない罠
罠多すぎ。。
>>979 「voidを指す」の意味がわかりません。
void 型へのキャストって「変数(の値)が一度も使用されていない」 などの警告を回避する目的以外にどんな場合で使われるんだろう。
>>985 煽りじゃないが,一応void型じゃなくてvoid*型な。
あ? (void)printf()?
>>988 printf() を void キャストするとどうなるんですか?
>>989 lint の警告(戻り値が捨てられている)が出なくなる。
・lintが静かになる。 ・I/O error処理なしの糞Cプログラムに。 ・そういうことにしたいのですね:)
あ、 ・compilerが"pop"する確信を持てるようになる。 を忘れた(w
>>989-990 lint 対策ですか。関数の戻り値までチェックしてるんですね。
ありがとうございました。
新スレ立てれなかった。誰か立てて下さい。
996
↓お前が必ず立てろ。
やっぱり次すれがたったのね。
ついで。
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。