1 名前:デフォルトの名無しさん mailto:sage [2008/03/09(日) 19:37:43 ] C++に関する質問やら話題やらはこちらへどうぞ。 ただし質問の前にはFAQに一通り目を通してください。 IDE (VC++など)などの使い方の質問はその開発環境のスレに お願いします。
116 名前:デフォルトの名無しさん mailto:sage [2008/03/19(水) 15:15:14 ] cinから一行読み込み+istringstreamで良くね? string line; getline(cin,line); stringstream linestream(line);
117 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 15:40:59 ] #define Max 1000 みたいなのを、グローバル変数を使って const int Max = 1000; とした方が良い(型指定ができるから)、と読んでる本で出てきました。 色んな所で「グローバル変数はできるだけ使うな」と言われていたのでびっくりしてしまったのですが、 こうやってconstにして#defineの代わりにするのは例外的によく使われるものなのでしょうか?
118 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 15:46:50 ] defineよりはマシってだけの話。
119 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 15:52:08 ] グローバル変数の議論とはまた別の話しだろ
120 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 15:56:36 ] >>117 グローバル変数がダメなだってだけ覚えてて、なぜダメなのか考えたこと無いみたいだね? 大雑把に言うとどこで変更してるか分からないから把握しづらいといったとこです const つけた場合(やろうと思えばできるけれど)変更できないので、そういう害は無い
121 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 15:58:48 ] あほすぎるw
122 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 16:53:57 ] 別の翻訳単位で参照する可能性のある“変数”ならグローバル変数を使う。 別の翻訳単位で参照する可能性のある“数値”なら#define定義のあるヘッダを各自インクルードすればいい。
123 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 17:11:37 ] >>122 なに言ってんの?w
124 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 17:12:31 ] const ついてるやつはグローバル定数と呼ぶべきもの。
125 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 17:17:00 ] >>117 グローバル変数に限らず、「○○はよくない」などと言われる物は絶対にダメという意味ではない。 ○○以外の有効な手段があればそれを選べという意味であって、○○が有効となる限られたケースでは使っていい。
126 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 17:18:31 ] 理由を理解せずに規約に従っても意味がない事の典型だな
127 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 18:31:27 ] >117 基本的にマクロは(特定の使い方以外)使わない方がいい。 マクロはプリプロセスで処理されてしまうため、コンパイルエラー時に酷い目に会う。 グローバル変数も使い方が難しいけど、コンパイラが識別できるものなのでマクロより余っ程マシ。 エラーが発生してもあくまで“変数”なので、マクロと違って識別名が普通に表示されるので トレースしやすい。 因みに言うと、グローバル変数にするかどうかは「その値がどの範囲まで影響するか/正しいか」というのを 考えて決めるべき。プログラム中で一意な定数は積極的にconstグローバル変数にすべきだわな。 ……しかし、こういう「疑問点を自ら追求する力を付ける」のがゆとり教育だったはずなんだけどね。 やっぱり失敗だったのか……
128 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 18:37:15 ] なんで勝手に117をゆとり教育を受けた人認定してるんだよ
129 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 18:41:28 ] エスパーするとC++でなく、Cの人が居ます。 「const リンケージ」でググって下さい。 >>117 C++で、それはただの定数で 変数のように書き換えることは出来ません。 グローバル変数が嫌われる主な理由は、 どこで書き換えられるか、把握し辛いことにあるため、 定数には当てはまりません。
130 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 18:56:40 ] どう見てもゆとりです、本当にありがとうございました。
131 名前:デフォルトの名無しさん mailto:sage [2008/03/20(木) 20:02:06 ] 1. マクロ定数はアドレスを完全に持たない。 (const 定数はアドレスを取得しようと思えばできるが、 アドレスを取得しさえしなければデータがデータメモリ上に置かれるとは限らない) 2. const 定数は名前空間に所属できる。 (マクロには名前空間がないため、名前被りが発生する可能性が大きい) 3. 値を求めるのに何らかの処理を伴う定数を使う場合、マクロだと毎回コードが埋め込まれてしまう。 (最適化が効く範囲ならいいのだが) 4. const 定数の方がコンパイルエラーが読みやすい。 (マクロの場合、置換後のテキストを元にしてエラーが出力されてしまう) 5. マクロの場合、型を明確に指定するには明示的なキャストが必要になる場合がある。 (見た目の問題でしかないと言われればそれまでだが) 6. ローカルスコープ内であっても、マクロ定数と同名の識別子を作ることはできない。 (作れない方がいいという意見もあるのかもしれないが) 7. const 定数を使うと副作用が一切無いことが明示される。 (キャスト演算子をオーバーロードしているクラスのオブジェクトの場合は例外だが)
132 名前:デフォルトの名無しさん [2008/03/21(金) 11:21:21 ] 質問があります。 動的配列を解放するときは要素数とかバイト数を指定しなくても delete [] p; でokですが、これはポインタpが指している動的配列の先頭バイトの 前に4byteの領域が確保されていて、ここに動的配列のバイトサイズ が格納されているから、delete時にサイズを指定する必要がないと 聞いたことがあります。 しかし、動的配列の総バイト数はわかるとしても、要素のバイト数 の情報はどこに格納されているのでしょうか? int *p; なら1要素のバイト数は4、double *p; なら1要素のバイト数は 8ですが、実行時にこの情報はどこから取得するのでしょうか? ポインタpそのものは先頭1バイトのアドレス情報しか保持して ませんから、こういう疑問をもった次第です。
133 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 11:30:24 ] ポインタそのものにそのアドレスに何が格納されてるかの情報は含まれてる。 そうでなければ cout << *p << endl; とかやったときに何が表示されるか未定義になってしまうじゃないか。
134 名前:デフォルトの名無しさん [2008/03/21(金) 12:15:53 ] >ポインタそのものにそのアドレスに何が格納されてるかの情報は含まれてる。 ありがとうございます。 ポインタは、単に先頭バイトのアドレスを格納する4バイトの記憶 場所をもっているだけでなく、動的データ(または動的配列の要素) のバイト数とか、データが文字なのか、整数なのか、実数なのか、 といった情報も裏側にもっている。これらの情報はポインタが指す 動的変数や動的配列側にではなく、ポインタ側にある。 という理解でよろしいでしょうか?
135 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 12:21:02 ] >>134 違う。ポインタの型によって静的に決まる
136 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 12:21:50 ] 静的に型付けされてるからそんなものは要らない。
137 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 12:23:04 ] まさかvoid*をdeleteしてないよな… あとポインタが4バイトとは限らないぞ。
138 名前:デフォルトの名無しさん [2008/03/21(金) 12:30:09 ] うーん、わからなくなってきました。 文字型変数、整数型変数、実数型変数がコンパイル時に静的に 型付けされているのと同じというのは概念的にわかります。 しかし、自分が質問しているのは、その静的な型付けをどのよう なしくみで実装しているのか?ということだろうと思います。 この段階にくると、コンパイラやアセンブラが理解できないと 無理なんでしょうけど。
139 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 12:50:07 ] 実行時に要素のバイト数は、どこにも格納されてない。 と、考えて良い。 コンパイルする時点では、当然型が分かるので、それを使う。 この段階というか、かなり基礎。 ※RTTIは上記が理解出来た上で。
140 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 12:59:28 ] >>138 いっぺん、自作クラスにoperator newとoperator deleteを実装してみればいいんじゃないかな。 乱暴な説明だけど、C++には「確保/削除するバイト数を受け取る、new/delete一族の大ボス的存在」である ::operator new(size_t)と::operator delete(void*, size_t)があって(他にも多重定義があるけど、とりあえず今はこの2例)、 たとえば int* p = new int; なんてのは、int* p = ::operator new(sizeof(int)); みたいにコンパイル時に解釈される。 同じく、後にdelete p; が出てきたら、pがint型のポインタなのはコンパイラにはわかるから(てか俺等にだってわかる)、 こっちは ::operator delete(p, sizeof(int)); になる。
141 名前:デフォルトの名無しさん [2008/03/21(金) 13:24:09 ] >>138 >int* p = new int; なんてのは、int* p = ::operator new(sizeof(int)); int *p= new int [100]; は int *p=::operator new(sizeof(int)*100); みたいになるんでしょうけど、要素のサイズが2バイトなのか4バイト なのかの情報をコンパイル時にポインタに付加しておかないと、p[i]の アクセスがうまくいかないのではないかと思うのですが、どうでしょうか?
142 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 13:25:59 ] >>141 p[i]のpの型はコンパイル時に分かってるんだから
143 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 13:44:43 ] まあ、強いて言えば、生成されたコード内に埋め込まれているって感じなのかな。 delete[] p;するときに、各要素のデストラクタを起動しなければならないわけだけど、 要素数は p = new T[count]; のcountで、実行時に変わる可能性のあるものだから、 ポインタの前かなんかに隠しておかなければならないわけ。 ちなみに、メモリブロックを単純に解放するだけなら要素数を隠しておく必要はないよ。 free()にサイズを指定しないでしょ? メモリマネージャはメモリブロックの総バイト数をどこかに隠しておくかもしれないけど、それは別の話。 あとは、 T *p; for(size_t i = 0; i < count; i++){ p->destruct(); ++p; //←これ } これの++pがどうコンパイルされるかという、>>139 が言うようにC言語レベルの基本的な話。
144 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 13:56:21 ] >>141 > p[i]のアクセス たとえばintが4byteの環境だとすると、p[i] と書かれた箇所はネイティブコードにおいては 「pのアドレス+i*4byteのメモリアドレスへ行ってそこから先4byte分に書き込まれているビット配列を〜」 という風に、既にintが「4byte」というミもフタも無い表現に変わっているから、型情報も何も関係無いよ。
145 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 14:27:51 ] >>141 p[i]というコードはコンパイルすると、アドレスはp+4*iといった意味の命令が生成される。 4が出てくる理由はpの宣言int* pによるもの(intが4byteの環境の場合)。
146 名前:145 mailto:sage [2008/03/21(金) 14:36:28 ] すまん、144と同じ事書いてしまった。
147 名前:141 [2008/03/21(金) 17:03:54 ] 返事が遅くなってすみません。みなさん、ありがとうございます。 >>144 さんと >>145 さんの説明で 4byteという要素バイト数の情報をポインタp自体が保持して いるのではなく、p[i]にアクセスする際にコンパイラがp+4*i を計算する命令を生成しているだけ、ということがやっと理解 できました。
148 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 18:35:45 ] 配列 new の場合、アップキャストは行わないから 配列のサイズは型から静的に決まる、と。 というか、アップキャストはできない。 そこが鍵だな。
149 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 18:36:13 ] ×配列のサイズ ○要素のサイズ
150 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 18:44:36 ] C++ 的にはフォーマットの決まった string の中から数字を 読み出したりするにはどうするのがお薦めなのでしょうか? 例えば string s("# foo 30 bar 0.1 xlajkdfl;ajkds"); から 30, 0.1 を抜く場合。 int n; double x; sscanf(s.c_str(),"# foo %d bar %lf",&n,&x); としたりするのですが、もっと「本来」の方法はあるのでしょうか? どうも workaround 的な気がするので。
151 名前:デフォルトの名無しさん [2008/03/21(金) 18:48:30 ] atofで一つずつ進めて数値になる所を取り出す
152 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 18:51:36 ] それはないな
153 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 19:53:08 ] 自分で字句解析器を書く。
154 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 20:00:28 ] 各種正規表現ライブラリの後方参照を使う
155 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 20:29:16 ] >>150 そういうのが必要になる状況ってあまり無くない?
156 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 21:08:24 ] >>155 俺はソースコード解析したい時によくでる。 字句解析ライブラリもってこいって話だよな・・・
157 名前:デフォルトの名無しさん mailto:sage [2008/03/21(金) 21:51:06 ] 字句解析なら分かるんだけど、>>150 は何か違う気がしたんで・・・ そうなら、分割の話から入るだろうし。 もしかして自然言語文からの抽出とかかな?
158 名前:150 mailto:sage [2008/03/21(金) 23:35:25 ] 皆様どうもありがとうございました。私は結構こういう必要に出会います。 主にデータファイルをフォーマットし直したり、それを処理する場合です。 例えばデータフォーマットの情報などた先頭にあったりして、その情報を 元に解析したりする場合です。無視して決め打ちする事も可能な場合も多い ですが、安全性のために整合性をチェックしています。 >>154 さんの方法が私には合っていると思います。普段 Ruby とかも使って いて正規表現も使っているのに惰性で C 的にを使い続けてる自分の頭の堅さ には呆れました。基本的に以下のようなコードで対応することを考えています。 まだあまり考えていないのでもう少しエレガントに書けるだろうとは思います。 string s("# foo 30 bar 0.1 xlajkdfl;ajkds"); boost::regex r0("^# foo ([0-9.]+) bar ([0-9.]+).+"); boost::match_results<std::string::const_iterator> mr; if(boost::regex_match(s,mr,r0)){ const int n = boost::lexical_cast<int>(mr.str(1)); const double x = boost::lexical_cast<double>(mr.str(2)); cout << n<<"\t"<<x<<endl; }
159 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 00:19:27 ] >主にデータファイルをフォーマットし直したり それまさに字句解析の範疇な気がするけど・・・w まぁ正規表現で簡単に済めばそれで良いと思うけどね。
160 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 12:44:30 ] >>159 > まぁ正規表現で簡単に済めばそれで良いと思うけどね。 regex ってかなり強力だと思う。テキストから情報拾う場合 に regex では簡単に通用しない場合ってどういうケース?
161 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 13:14:39 ] >>160 ネストした括弧の対応を取るとか
162 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 14:07:16 ] そこでboost::xpressiveですよ
163 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 14:15:50 ] boost もいろいろあってわからんなぁ。xpressive だと簡単なのかな。 俺だと char ごと読み取って '(' ')' を +1, -1 でカウントするとか 低レベルな事を考えちゃうけど。
164 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 14:52:00 ] 通常の正規表現では任意のネストを表現することができない。 →xpressive ではパターンの自己再帰記述が可能。 →正規表現の枠を超える表現力を持つ(文脈自由文法)。 →xpressive だとネストの対応が可能。
165 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 15:01:28 ] boostの文字列処理ライブラリの事ならboost本のサンプルで読めたな
166 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 15:21:10 ] boost 本でお薦めってある? 本あまり出てないよね。 Karlsson の本は目を通したけど感じは判ってよいけど便利な本 という感じではない。秀和から出てる稲葉さんは本厚いし内容あるのかな。
167 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 17:31:22 ] inabaさんのは導入+軽いリファレンスにはいいかも おおまかな概念と使用例が載ってる boostもう使ってるよ〜という人にはあまり必要ないかも
168 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 17:31:23 ] 複数の派生クラスがそれぞれ値の異なるconst staticなメンバ変数をもっていて、 基底クラスへのポインタを使って読み取りたいのですが、どうすればいいでしょう 基底クラスへのポインタの配列に、いろいろな派生クラスを突っ込んでいる状態なので、 直接アクセスすることは出来ません
169 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 17:49:42 ] ttp://www.s-cradle.com/developer/sophiaframework/tutorial/Cpp/virtual.html
170 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 17:54:12 ] >>166 C++ Template Metaprogramming
171 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 17:56:20 ] >>168 普通に仮想関数で struct Base { virtual StaticMemberType GetStaticMember()=0; }; struct DerivedA : public Base { StaticMemberType GetStaticMember { return DerivedA::staticMemember; } }; あるいはRTTI使ってマルチメソッド。
172 名前:171 mailto:sage [2008/03/22(土) 17:59:13 ] ごめん引数1つのマルチメソッドはないなw
173 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 18:22:26 ] あー、関数をアクセサにすればよかったですね。何やってんだ俺 ありがとうございました
174 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 21:56:34 ] >>170 どうもありがとうございます。実はその本は持っていて次に読む予定。 しかし、これも洞察には優れているとは思うけど、便利な本では ないかも。面白そうなんで期待してるけど。
175 名前:デフォルトの名無しさん mailto:sage [2008/03/22(土) 22:03:15 ] >>174 面白くないよ。mplの単なるリファレンス。
176 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 00:53:31 ] DLLを読み込み、一部の機能のみを使った場合、 メモリの消費量はまるまるDLL分増えるのでしょうか それとも使った機能の分だけ増えるのでしょうか
177 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 01:03:35 ] 環境依存の話はスレチだけど、まるまる増えると思うよ。
178 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 01:12:30 ] 仮想メモリはまるまる 物理メモリはコードについては使った分 データはシラネ
179 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 01:30:13 ] ありがとうございました 使いたいライブラリが8MBくらいあるもので、 まるまる増えるのはちょっとアレかな、と思って質問しました 改変可なので、必要な部分だけ取り出そうと思います
180 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 03:06:24 ] Managerクラスがあり その機能は、一部のクラス(と言っても10個ぐらいある><) にしか利用できないって設計の場合 一部のクラスをfriendする以外に何か方法はありませんか?
181 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 03:13:01 ] その一部のクラス以外はmanagerクラスのインスタンスを手に入れられないようにする。
182 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 09:41:11 ] >>180 freind じゃダメな理由を書いた方が答えが得られやすいと思う。
183 名前:>>182 mailto:sage [2008/03/23(日) 09:42:51 ] ミスった... orz freind ⇒ friend
184 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 09:45:07 ] friend先に依存が出来るからじゃね? 普通、friendは最終手段だし
185 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 12:07:26 ] そんなことはない。
186 名前:>>182 mailto:sage [2008/03/23(日) 13:05:05 ] friend 先に依存って何?
187 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 13:58:48 ] 一部のクラスだけ特別扱いするというのがManagerクラスの仕様なら、 friendによる依存は妥当だと思う。
188 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 14:45:51 ] 一部のクラスの基底クラスとして Manager を取得するクラスを作って、 その1つだけを friend にすれば?
189 名前:180 mailto:sage [2008/03/23(日) 14:58:22 ] friendが結構な数になってしまうんです。 下手すれば私のリアルfriendより多いぐらい それが悔しくて
190 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 14:59:16 ] 誰が上手い事を言えと
191 名前:184 mailto:sage [2008/03/23(日) 15:01:24 ] 俺は181に一票で
192 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 15:02:43 ] その方法を聞いてるんだろw
193 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 15:09:28 ] パスワード掛ければいいんじゃないですかね
194 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 15:14:48 ] w
195 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 15:25:03 ] 権限プログラミングってのも面白そうじゃないか
196 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 15:42:23 ] singletonなら簡単なのにな
197 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 16:01:39 ] 思い出したw ____ |← reject| boostの中の人 singleton ユーザー . ̄.|| ̄ ̄ ┗(^o^ )┳(`Д´)┳(^o^ )┛≡=- || ┏┗ ┗┗ ┏┗ ≡=-  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
198 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 16:06:07 ] ユーザーは欲してると思うが
199 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 16:34:52 ] にわかに得た知識で面白いこと考えた! Managerのインスタンスを受け取る関数の引数に関数オブジェクトを使って 内部で一定のアルゴリズムで正しい値を返すもの(パスワードの暗号化みたいな)にのみそのインスタンスを渡してやる風にすればいいんじゃね? 更にインスタンスを受け取る関数をテンプレート化してやり、欲しい権限までのクラス型インスタンスを返すようにしてやればアクセス制限も出来て完璧! とここまで考えてわざわざこんなことしてもオーバーヘッドが大きいだけなことに気づいた そもそも何の意味があるんだっけか
200 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 16:45:12 ] だから >>188 でいいだろ、別に。
201 名前:デフォルトの名無しさん [2008/03/23(日) 16:57:35 ] Managerクラスコンストラクタなどをprotectedにして、使うクラスはManagerを継承する。
202 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 17:02:41 ] >>188 >>199 >>201 これらの方法は、Managerクラスの許可なく好き勝手に権限のあるクラスを作れる。 そういうのを>>180 は制限したいんじゃないの?
203 名前:>>182 mailto:sage [2008/03/23(日) 17:08:28 ] >>201 そう言うのは最悪。 あとから見て、継承が本当に必要だったのか、単に特定のメソッドを 使わせるために継承しているのかがわからなくなるから。
204 名前:201 [2008/03/23(日) 17:21:39 ] >>203 意味がよく分からないけど、、、「特定にメソッドを使わせるために継承が必要かどうかがわからなくなる」ってこと? そんなこと言ってたら何もできない。 friendだったら、なぜfriendにしたか分からなくならないの? friend よりいいと思うけどな。 friend じゃprivateのメンバにアクセスできてしまう。 Managerクラスを機能を利用するんだから、継承しかないでしょ。 使う側のクラスに持たせるとなると、コンストラクタとかはpublicになってしまうし。
205 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 17:40:32 ] 継承すると Managerの中のstaticでない変数とか勝手に作られない?
206 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 17:41:03 ] >>203 Manager クラスじゃなくて単に許可コントロール用の class を作る というのは有りじゃない?そういう例をまともな本で見た記憶がある。
207 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 17:42:27 ] -カーズは- 2度と地球へは戻れなかった…。 鉱物と生物の中間の生命体となり 永遠に宇宙空間をさまようのだ。 そして死にたいと思っても死ねないので ―そのうちカーズは考えるのをやめた。 全部globalにすればいいじゃん
208 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 17:44:01 ] >>206 電波の缶詰の人のサンプルもそうだった ライブラリ的なものを 外部からいじられないようにするためだったら そんな感じでもいいんじゃまいか 村八分
209 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 17:47:19 ] Managerインスタンスを受け取るために、Managerにコールバックしてもらえばいいんじゃない? class FriendClassA; // 前方宣言 class FriendClassB; class Manager { public: class Friend { public: virtual void authorize(Manager* m) = 0; }; void getInstance(Friend* p) { if( dynamic_cast<FriendClassA*>(p) || dynamic_cast<FriendClassB*>(p) || /* 権限のあるクラスかをチェック */ ) { p->authorize(this); } } };
210 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 18:25:34 ] それは、インスタンス取るのに時間かかるし friendでいいじゃんって話になるも
211 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 18:40:51 ] 速度が重要ならtemplate部分特殊化とかで。 class Manager { public: template <class Unauthorized> static void authorizedProc(unauthorizedClass * p) { std::cout << "not authorized" << std::endl; } template <> static void authorizedProc(authorizedClassA * p) { p->Proc(m_instance); } // 以下許可するクラス分同じコード private: Manager m_instance; }; 冗長だし検証してないけど。
212 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 18:45:30 ] Manager を使えるクラスを作成する場合には ファクトリクラスを通すようにする。 で、そのファクトリクラスを friend にして、 そこで Manager クラスを取得して、 各クラスにそれを渡すようにする。 設定関数は各クラスの共通基底クラスに作って、 それをファクトリクラスの friend にする。
213 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 18:46:54 ] 先輩から聞いたのですが、extern "C" {}せずに構造体を宣言すると、 余計なクラス情報がくっつくって本当ですか?
214 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 18:52:41 ] そんなことは聞いた事が無いが、 特定のコンパイラでそういう事があるとかいうんだったら俺は知らない。
215 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 18:55:11 ] クラス情報って具体的には何なんだ?
216 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 18:57:34 ] >>213 マングリング名にクラス情報がくっつくって話だと思う。