C++に関する質問やら話題やらはこちらへどうぞ。 ただし質問の前にはFAQに一通り目を通してください。 IDE (VC++など)などの使い方の質問はその開発環境のスレに お願いします。
STLつかうと一気に実行ファイルサイズが10倍に?! 環境によるだろ。 俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力 ランタイムを使用するようにして使っているが、例えばstd::vectorを 使っても使わない時と比べ10Kほどしか増えない すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。 C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいの? #include <stdafx.h> 後死ね。 言葉が悪いな。それで教えているつもりか。 まぁヒントぐらいにはなったな。 うむごくろう。
>>前スレ1000 とりあえず、お前が俺の言っていることを理解出来ていないことだけは分かった お薦めの本があって、それを教えることには全く反対しないが、 自分で調べたり、情報を探したりしようとしない奴は 大体どうしようもない 一応補足 前スレ984のように聞いてみること自体は別に良いと思う 本を紹介してもらわないと先に進めない、ということでなければ
お前のポリシーはどうでもいいよ
そういや、こういうヤツがいるから初心者歓迎スレが出来たんだったな
ポリシーじゃねぇよ・・・
無能にレスしても無駄のようだな・・・
>>10 初心者に本だけでなく入門サイト探してみたら?って言うのは
アドバイスにならないのか?
自分自身の経験から言っているんだけど
ある程度理解出来てくるとcppllのアーカイブとかも参考になるし
おとなしく初心者歓迎スレかオススメ図書スレに誘導してやれよ 今回の様な議論が過去あったからこそそういったスレがあるんだから
誘導済みだろ? 俺は別に質問者にレスしてるつもりないし・・・ 前スレの985のレスが気に食わない人が居るようなので、 レス返してるだけ
>>13 案外質問した人が突っ掛ってたりしてなw
んなわけないか。
他スレでis-a、has-aで継承やメンバを考えるみたいな話が合ったんですが、 doはどういう風に処理したらいいでしょうか アクションゲームとかでAn enemy moves.(敵は動く)とした場合、 moveメソッドはenemyオブジェクトの位置を示すメンバ変数を操作すると思います。 すると、moveはenemyオブジェクトのメンバ関数であるべきと思えるのですが、 他のオブジェクトの位置とかが影響する場合、 enemyオブジェクトをメンバにもつクラス(WorldとかGameとか)に、 全てのオブジェクトを動かすメンバ関数を用意した方が、 他のオブジェクトを参照でき適切に処理できそうです このような機能を持つメソッドを、皆さんはどの位置に配置していますか?
enemyのmoveメソッドはそのままで WorldやGameからすべてのenemyのmoveメソッドを呼ぶ様にすればいいんじゃね? ていうかC++関係ないな
>>16 すみません、自身がCからC++に移行して、
クラス設計に右往左往しているもので、ここで聞いてしまいました
>>17 あ、そんなスレがあったとは知りませんでした
moveメソッドは引数にしたがってオブジェクトの変数を変えるだけ
moveメソッドに渡す引数を敵戦略クラスないし、Worldクラスで決定するって方向で考えて見ます
(moveメソッドの内容が二行で終わりそうだ……。他のメソッドとまとめよう)
ありがとうございました
飛んできたのはおそらく同じ板のシューティング製作スレだなw
21 :
17 :2008/03/10(月) 02:11:11
ターン制で移動先選択→攻撃みたいなの想定してました/(^o^)\ 敵戦略クラスは忘れた方が良いw
Class().Method(); なんて書けたんだね、、、知らなかったよ(;´Д`)
式が何を意味するかによる。Class()がインスタンスなら当然ドットを付けてメンバにアクセスできる。 一通り文法をかじったなら、今度は仕様書を読んでそれを確かなものにした方がいい。流れとしては。
ぁぁ、ごめん。はしょりすぎた。 class Class { public: int Method(); }; こんなので、 void F() { printf( "%d\n", Class().Method() ); } な感じ。
printf("%d\n", int(5)); な感じ?
一時オブジェクトが近々move semanticsな感じ?
異なるクラスのオブジェクトをひとつの配列(vector,list)で管理することは出来ないのでしょうか a[0]はclassA,a[1]はclassB,a[2]はclassC、……という風に classA、classBは同じpublicなメンバを持っているのですが、 メンバ関数の中身とそこで使うprivateなメンバが異なっています
>>28 関数の多重定義のことでしょうか
ClassAとClassBの異なるメンバもひとつのクラスにまとめて、
使わないメンバがあっても気にしない、という方針でもいいんですが、
無駄にメモリを消費するのがイヤなもので
全く関連のないクラスを1つの配列に入れるという時点でかなりおかしいと思う。 関連というか共通項があるからこそ1つの配列に入れるんだろう?
>>29 仮想関数ってやつだ。
class Base {
public:
virtual ~Base() {}
virtual void func() = 0; // 共通のメンバ関数
};
class A : public Base {
public: virtual void func() { /* classAの処理 */ }
private: /* classAのメンバ変数 */
};
class B : public Base {
public: virtual void func() { /* classBの処理 */ }
private: /* classBのメンバ変数 */
};
このようにしておいて、たとえば
Base* p1 = new A;
Base* p2 = new B;
とすれば、
p1->func(); // A::funcが呼ばれる
p2->func(); // B::funcが呼ばれる
となる。
あとはvector<Base*>にすれば万事解決では。
boost::ptr_vector だと勝手に delete してくれるから楽だよ。
>>30 アクションゲームで
A:単純な移動しかせず体当たりでダメージを生む敵
B:主人公の位置などを頼りに複雑なアルゴリズムで動き多彩な攻撃をする敵
こんな感じでAの方が圧倒的に必要なメンバ変数が少なく、
かつAの方が数が多いので、Bに合わせてメンバ関数を増やすとメモリを食らってしまうのです
>>31 >Base* p1 = new A;
AがBaseを継承していると、こんな代入も可能なのですか……
ありがとうございました
>>32 ググってみましたが、new演算子を使いまくるなら、便利そうですね
仕様に慣れるよう練習してみます
あちがとうございました
誤字修正 ×Bに合わせてメンバ関数を ○Bに合わせてメンバ変数を
>>33 とりあえず
継承、多態(ポリモーフィズム)、オーバーライド
等を調べるんだ
AとBの共通する部分を基本クラス(やinterface)としてくくりだせ
エピステーメー氏の「C++言語のカラクリ」の話題出た? なめて読んでたら「自己記述の必然性」が全く理解できない。 どうにか「だから単純なC++→C」のコンバーターじゃ駄目なんだよって 一言で説明できないか?
C++をC++で記述できないとだめだということ? 何だかよく分からないな。でもあの人はたまに哲学よりのトンデモを平気で書いたりするから気にしちゃいけないよ。
Cだけではtrr..catch..throwが実現できなかったって話だろ。 でも話題が古いなあ。
自己記述できることが○○だ(スバラシイとか完備だとか) って誰かに刷り込まれたんかな 頭悪いな
コードジェネレータ通すとデバッグがやりにくそう
VMのスタック上で記号処理を介せば 殆どの言語は自己記述可能だが と書けばミもフタもないのか
IO機能がないんですがどうすればいいですか。
42は41へのレスなんじゃなかろうか
orz
自己記述ってどんなの?
ある言語やその処理系でその言語を実行できる処理系を書くことだお
多分要はメタプログラミングは必要だから出てきたんだ、偶然や酔狂じゃない。 ってことを言いたいんだろ?読んでないけど。
あれ?なんかtemplateで遊んでたらメタプログラミングできちゃったぞ って感じ
typedef std::map<size_t,Dummy> DummyMap; DummyMap dmap; .... DummyMap::iterator it = dmap.find(index); Dummy& dummy = (it != dmap.end()) ? it->second : dmap[index]; っていうこと(イメージ)をしたいんだが、\ findして、insertすると少なくとも2回の走査が行われていて、無駄な感じがする。 どうすべきか、アドバイスをくだされ。
趣旨を間違った。 これじゃ普通にdmap[index]すればいいじゃねーか。 出直してくる。
>>51 定型はこう、かな
iterator it = map.lower_bound(key);
if(it == map.end() || it->first != key) {
it = map.insert(it, Dummy());
}
Dummy &d = it->second;
> it->first != key これは問題なければ良いんだけど、正確にはlessを使えとかそういう話、無かったっけ?
it->first != key lower_boundの戻り値はpairじゃないよな。確かキーだよな。 ソート基準がデフォのlessならこうか。 if(it != map.end() || !(key < *it)) { //found } else { //not found }
||じゃなくて&&だわ if(it != map.end() && !(key < *it)) { //found } else { //not found }
>>55 lower_bound()の戻り値はpairだよ。
・・・というより、map<k, v>::value_typeがpair<k, v>だ、と説明するほうが、根本的で適切かな。
std::コンテナ::iteiratorは、std::コンテナ::value_typeのポインタ的に動作するわけだから。
>>53-54 「厳密には」こう書くべき。
if (it == map.end() || map.key_comp()(key, it->first) {
ごめん訂正。 - map<k, v>::value_typeがpair<k, v> + map<k, v>::value_typeがpair<const k, v>
>>57 ああ、そうだね。elementの型がpairだた。スマソ。
60 :
デフォルトの名無しさん :2008/03/16(日) 05:51:19
テスト
61 :
デフォルトの名無しさん :2008/03/16(日) 05:55:48
class B; class A { B b; }; class B { A a; }; と書いたところ、 エラー出ます><。 どう対処すればいいですか?
よく考えようぜ。 A の中に B がある。 その B の中に A がある。 その A の中に B が・・・ あり得ない。 とりあえず何をしたいのか整理しよう。 大抵の場合は、 1. クラス設計を変更する。 2. a と b のどちらかを参照にする。 のどちらかになる。
haskellを使う
>>61 Aの中に持ちたいのはBそのものじゃなくて、Bの参照なんじゃね?
62にそう書いてるじゃん
くだらない質問で申し訳ないのだけど、どなたか教えてください クラスのコンストラクタで関数名の後ろにつけている初期化みたいなものの意味を教えてください hoge::test() : a(0),b(0),c(0) { ... } この場合だとa=0,b=0,c=0? だとしたらなぜ...のところに書かないのですか?
test
test()じゃエラー出ると思う hoge::hoge() : a(0),b(0),c(0) { ... } のことだよね aが変数だと問題ない?けど aがクラスの場合、aのコンストラクタに0という引数渡すということ。 class a{ public: a(int value); }; みたいなクラスの場合、aのコンストラクタに数値渡さないと作成できないし
変数とクラス名が同じだとエラー出るや class A{ public: A(int value); }; class hoge { A a; public: hoge() : a(0) { ... } }; ってこと この場合 ...の所に a = 0; って書けない
>>67 前者は初期化で、後者は何らかの初期化、または未初期化で構築の後、代入だな。
どちらでも良い場合はあるけど、意味は明確に違う。
例えばconstが絡んだ場合とか、
class hoge{
const int a; //constなので代入できない。
};
>>69 のようにメンバの構築に引数が必要な場合とか。
未初期化な変数を嫌ったり、デフォルトコンストラクタの後に代入するような
効率の悪さを嫌ったり、色々あるからできるだけ初期化を使う。
CとC++の違いを徹底解説!みたいな本に Class::Method():field(0),field1(0) { } なんて書いてあってさ、 何だよコンパイラバグってんじゃねーか!とか思ったころがあった
ていうかさ、constメンバや参照メンバもそうだけど 基底クラスの初期化も、この形式じゃないと出来ないよ。 もちろん、引数なしのデフォルトコンストラクタでの初期化は可能だけど。
75 :
72 :2008/03/17(月) 11:55:05
「オブジェクト指向言語C++入門 Cとの違いを徹底追求」 これかな。 やっぱり古いのもあってか、<string.h>とか、 namespace、例外の話はまったくなかった。 それ意外と、多少の誤植を除けば、解り安くもなければ解りづらくもない中立的な本だった。 まぁ、今となっては読むべき本じゃないわな
低レベルな質問は初心者スレでやれ
関数の戻り先アドレスがバッファオーバーランで壊されているようなんですが、どこで壊されているのかが分かりません。 a(){ b(); } b(){ // ログに戻り先アドレスを記録 /* 処理1 */ // ログに戻り先アドレスを記録 /* 処理2 */ // ログに戻り先アドレスを記録 return; } あたりをつけるために、上のように処理の区切りで関数の戻り先アドレスをログにはき出そうと思うんですが、 戻り先アドレスをどのように参照していいかが分かりません。 もし分かりましたら、参照方法を教えてください。 よろしくお願いします。
環境に依存します
>>78 そこまで推測できているならデバッガでスタックにトリガ張ればすぐだろうし、
そうでなくてもコンパイラにスタックのチェックをするオプションがあったりしないか?
そもそもバッファオーバフローだと判っているなら関数内のポインタを全部洗えばいいだけじゃん。
# 巨大関数だったらしらねw
>>79 失礼しました。
Windows2000 VC++6です。
>>80 それが、1ヶ月に1度位しか発生しないエラーなのでトレースが困難なんです。
各所にログを埋め込み、関数から戻ってこないのは確認できたので、戻り先アドレスが壊されているらしいと推測したんです。
次はどこで壊されるかをログに記録し、また1ヶ月待ってみようと思いましてw
espでも記録しておくとか
>>81 >79の時点でスレ違いだと気付こう。
>そうでなくてもコンパイラにスタックのチェックをするオプションがあったりしないか?
>>83 申し訳ありませんでした。
色々なアドバイスありがとうございました。
const T &なメンバをもつクラスを作ったんだが、 ひょっとして、コピーする手段がない?
クラス初期化にしかconst T &は初期化できないから まぁなんというか頑張れ
コピーコンストラクタならおkだが、operator=はダメだろうな
const_ca
なんで&があるん? *だけじゃ駄目なん?
駄目です
なんで
インラインアセンブラ使えばコピーできないことはないだろうが 当然おすすめはしない。
93 :
デフォルトの名無しさん :2008/03/18(火) 01:32:09
関数gがコンパイルエラーになります。なぜですか?不可解です。 class X { protected: int val; }; class Y : public X { public: void f(Y* p) { p->val = 0; } // OK void g(X* p) { p->val = 0; } // エラー };
X::valはYから見ればprivate Y::X::valはYから見ればpublic
あ、いや、privateというべきじゃなくprotectedでいいのかな。どっちだろ。 いずれにせよYからX::valは触れない。Y::X::valなら触れる。
96 :
93 :2008/03/18(火) 02:05:40
>>95 やっぱりそうですか。なんとなく奇妙な言語仕様に思えるのですが。。。
じゃなぜこういう風に難解なルールになっているか逆に考えてみればわかる。 class Y2 : public X { void f(Y* p) { p->val = 0; } }; というXを継承した別のクラスを作ってみよう。YとY2は別のクラスなのでY2から Yのprotected属性のメンバ変数が変更出来てはまずいのに、もしこのような ルールがなかったら上の例で可能になってしまう。 モジュールの隠蔽が破られないように特別なルールが作られているわけだ。
98 :
93 :2008/03/18(火) 02:33:25
なるほど。なんとなくですが、分かりました。
fseekgでstr.length()分を戻したいのですけど、 単にマイナスをつけて、-str.length()とするとイミフな数値しか出ません。 何でうまくいかないんでしょうか?
事故解決しました。 length()が返すのはsize_typeで、 size_typeはsize_tのunsigned intみたいだからですね。
出しかたによる。
この言語機能多すぎじゃね?
必要な部分だけ使え
>>102 少なくともsize_typeは符号無しということは標準で決まっている事柄だったと思う。
>>105 unsigned intとどこに書いてある?
お前は何を言ってるの?
>>106 それは規格のどこにも書いていないが、
例えばもし99=100が使っている実装のsize_typeが
仮にunsigned longやunsigned shortだったとしても、
99=100は同じように質問して同じように解決していたに違いない。
たまたま100の使っている実装でsize_typeがunsigned intだったこと以外は
標準C++で普遍的に成り立つ話じゃないか。
size_typeは符号なし整数。 ただしbit数は決まってない。
>>108 頭の悪い子って、「話の行きがかりで登場したディテール」と「そのディテールに依存した話」の違いが
わからないから困るよね。
少なくとも、「環境依存の話すんなくそったれ」と「unsigned intとどこに書いてある?」の2レスより、
「でも規格で決まってるのはunsignedってことだけだから注意」とか書くほうが簡潔で有用。
非・馬鹿は最初からこう書く。
size_t が unsigned long のこともよくあるしな。
unsigned short だったりすると -length() しても int 型で普通に負の数になったりして。
std::cinで文字や数値を入力するとバッファに改行文字が残るようで、 その後に std::getline(std::cin, buf, '\n'); とかやらせると残った改行文字だけ読み込んでしまいます。 バッファをクリアする方法がないかと調べてみたのですが、 環境に依存せず確実にクリアする方法はない、という記述がありました。 こういう場合はそもそもstd::cinを使わないようにするのがよいのでしょうか? fgetsとかを代わりに使えば改行文字まで読み込んでくれるみたいなのですが、 std::cinの方がすっきりしたコードになるので、他に問題を回避する方法がないか探しています。
>>113 cin.ignoreを呼ぶとかcin.getを繰り返すとかで十分では?
ああ、なるほど。 この場合はバッファに残るのが改行文字一個だけと分かってるから、それで十分なんですね。 ありがとうございました。
cinから一行読み込み+istringstreamで良くね? string line; getline(cin,line); stringstream linestream(line);
#define Max 1000 みたいなのを、グローバル変数を使って const int Max = 1000; とした方が良い(型指定ができるから)、と読んでる本で出てきました。 色んな所で「グローバル変数はできるだけ使うな」と言われていたのでびっくりしてしまったのですが、 こうやってconstにして#defineの代わりにするのは例外的によく使われるものなのでしょうか?
defineよりはマシってだけの話。
グローバル変数の議論とはまた別の話しだろ
>>117 グローバル変数がダメなだってだけ覚えてて、なぜダメなのか考えたこと無いみたいだね?
大雑把に言うとどこで変更してるか分からないから把握しづらいといったとこです
const つけた場合(やろうと思えばできるけれど)変更できないので、そういう害は無い
あほすぎるw
別の翻訳単位で参照する可能性のある“変数”ならグローバル変数を使う。 別の翻訳単位で参照する可能性のある“数値”なら#define定義のあるヘッダを各自インクルードすればいい。
const ついてるやつはグローバル定数と呼ぶべきもの。
>>117 グローバル変数に限らず、「○○はよくない」などと言われる物は絶対にダメという意味ではない。
○○以外の有効な手段があればそれを選べという意味であって、○○が有効となる限られたケースでは使っていい。
理由を理解せずに規約に従っても意味がない事の典型だな
>117 基本的にマクロは(特定の使い方以外)使わない方がいい。 マクロはプリプロセスで処理されてしまうため、コンパイルエラー時に酷い目に会う。 グローバル変数も使い方が難しいけど、コンパイラが識別できるものなのでマクロより余っ程マシ。 エラーが発生してもあくまで“変数”なので、マクロと違って識別名が普通に表示されるので トレースしやすい。 因みに言うと、グローバル変数にするかどうかは「その値がどの範囲まで影響するか/正しいか」というのを 考えて決めるべき。プログラム中で一意な定数は積極的にconstグローバル変数にすべきだわな。 ……しかし、こういう「疑問点を自ら追求する力を付ける」のがゆとり教育だったはずなんだけどね。 やっぱり失敗だったのか……
なんで勝手に117をゆとり教育を受けた人認定してるんだよ
エスパーするとC++でなく、Cの人が居ます。
「const リンケージ」でググって下さい。
>>117 C++で、それはただの定数で
変数のように書き換えることは出来ません。
グローバル変数が嫌われる主な理由は、
どこで書き換えられるか、把握し辛いことにあるため、
定数には当てはまりません。
どう見てもゆとりです、本当にありがとうございました。
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バイトのアドレス情報しか保持して ませんから、こういう疑問をもった次第です。
ポインタそのものにそのアドレスに何が格納されてるかの情報は含まれてる。 そうでなければ cout << *p << endl; とかやったときに何が表示されるか未定義になってしまうじゃないか。
134 :
デフォルトの名無しさん :2008/03/21(金) 12:15:53
>ポインタそのものにそのアドレスに何が格納されてるかの情報は含まれてる。 ありがとうございます。 ポインタは、単に先頭バイトのアドレスを格納する4バイトの記憶 場所をもっているだけでなく、動的データ(または動的配列の要素) のバイト数とか、データが文字なのか、整数なのか、実数なのか、 といった情報も裏側にもっている。これらの情報はポインタが指す 動的変数や動的配列側にではなく、ポインタ側にある。 という理解でよろしいでしょうか?
>>134 違う。ポインタの型によって静的に決まる
静的に型付けされてるからそんなものは要らない。
まさかvoid*をdeleteしてないよな… あとポインタが4バイトとは限らないぞ。
138 :
デフォルトの名無しさん :2008/03/21(金) 12:30:09
うーん、わからなくなってきました。 文字型変数、整数型変数、実数型変数がコンパイル時に静的に 型付けされているのと同じというのは概念的にわかります。 しかし、自分が質問しているのは、その静的な型付けをどのよう なしくみで実装しているのか?ということだろうと思います。 この段階にくると、コンパイラやアセンブラが理解できないと 無理なんでしょうけど。
実行時に要素のバイト数は、どこにも格納されてない。 と、考えて良い。 コンパイルする時点では、当然型が分かるので、それを使う。 この段階というか、かなり基礎。 ※RTTIは上記が理解出来た上で。
>>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]の
アクセスがうまくいかないのではないかと思うのですが、どうでしょうか?
>>141 p[i]のpの型はコンパイル時に分かってるんだから
まあ、強いて言えば、生成されたコード内に埋め込まれているって感じなのかな。
delete[] p;するときに、各要素のデストラクタを起動しなければならないわけだけど、
要素数は p = new T[count]; のcountで、実行時に変わる可能性のあるものだから、
ポインタの前かなんかに隠しておかなければならないわけ。
ちなみに、メモリブロックを単純に解放するだけなら要素数を隠しておく必要はないよ。
free()にサイズを指定しないでしょ?
メモリマネージャはメモリブロックの総バイト数をどこかに隠しておくかもしれないけど、それは別の話。
あとは、
T *p;
for(size_t i = 0; i < count; i++){
p->destruct();
++p; //←これ
}
これの++pがどうコンパイルされるかという、
>>139 が言うようにC言語レベルの基本的な話。
>>141 > p[i]のアクセス
たとえばintが4byteの環境だとすると、p[i] と書かれた箇所はネイティブコードにおいては
「pのアドレス+i*4byteのメモリアドレスへ行ってそこから先4byte分に書き込まれているビット配列を〜」
という風に、既にintが「4byte」というミもフタも無い表現に変わっているから、型情報も何も関係無いよ。
>>141 p[i]というコードはコンパイルすると、アドレスはp+4*iといった意味の命令が生成される。
4が出てくる理由はpの宣言int* pによるもの(intが4byteの環境の場合)。
146 :
145 :2008/03/21(金) 14:36:28
すまん、144と同じ事書いてしまった。
147 :
141 :2008/03/21(金) 17:03:54
返事が遅くなってすみません。みなさん、ありがとうございます。
>>144 さんと
>>145 さんの説明で
4byteという要素バイト数の情報をポインタp自体が保持して
いるのではなく、p[i]にアクセスする際にコンパイラがp+4*i
を計算する命令を生成しているだけ、ということがやっと理解
できました。
配列 new の場合、アップキャストは行わないから 配列のサイズは型から静的に決まる、と。 というか、アップキャストはできない。 そこが鍵だな。
×配列のサイズ ○要素のサイズ
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で一つずつ進めて数値になる所を取り出す
それはないな
自分で字句解析器を書く。
各種正規表現ライブラリの後方参照を使う
>>150 そういうのが必要になる状況ってあまり無くない?
>>155 俺はソースコード解析したい時によくでる。
字句解析ライブラリもってこいって話だよな・・・
字句解析なら分かるんだけど、
>>150 は何か違う気がしたんで・・・
そうなら、分割の話から入るだろうし。
もしかして自然言語文からの抽出とかかな?
158 :
150 :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;
}
>主にデータファイルをフォーマットし直したり それまさに字句解析の範疇な気がするけど・・・w まぁ正規表現で簡単に済めばそれで良いと思うけどね。
>>159 > まぁ正規表現で簡単に済めばそれで良いと思うけどね。
regex ってかなり強力だと思う。テキストから情報拾う場合
に regex では簡単に通用しない場合ってどういうケース?
そこでboost::xpressiveですよ
boost もいろいろあってわからんなぁ。xpressive だと簡単なのかな。 俺だと char ごと読み取って '(' ')' を +1, -1 でカウントするとか 低レベルな事を考えちゃうけど。
通常の正規表現では任意のネストを表現することができない。 →xpressive ではパターンの自己再帰記述が可能。 →正規表現の枠を超える表現力を持つ(文脈自由文法)。 →xpressive だとネストの対応が可能。
boostの文字列処理ライブラリの事ならboost本のサンプルで読めたな
boost 本でお薦めってある? 本あまり出てないよね。 Karlsson の本は目を通したけど感じは判ってよいけど便利な本 という感じではない。秀和から出てる稲葉さんは本厚いし内容あるのかな。
inabaさんのは導入+軽いリファレンスにはいいかも おおまかな概念と使用例が載ってる boostもう使ってるよ〜という人にはあまり必要ないかも
複数の派生クラスがそれぞれ値の異なるconst staticなメンバ変数をもっていて、 基底クラスへのポインタを使って読み取りたいのですが、どうすればいいでしょう 基底クラスへのポインタの配列に、いろいろな派生クラスを突っ込んでいる状態なので、 直接アクセスすることは出来ません
>>166 C++ Template Metaprogramming
>>168 普通に仮想関数で
struct Base { virtual StaticMemberType GetStaticMember()=0; };
struct DerivedA : public Base {
StaticMemberType GetStaticMember { return DerivedA::staticMemember; }
};
あるいはRTTI使ってマルチメソッド。
172 :
171 :2008/03/22(土) 17:59:13
ごめん引数1つのマルチメソッドはないなw
あー、関数をアクセサにすればよかったですね。何やってんだ俺 ありがとうございました
>>170 どうもありがとうございます。実はその本は持っていて次に読む予定。
しかし、これも洞察には優れているとは思うけど、便利な本では
ないかも。面白そうなんで期待してるけど。
>>174 面白くないよ。mplの単なるリファレンス。
DLLを読み込み、一部の機能のみを使った場合、 メモリの消費量はまるまるDLL分増えるのでしょうか それとも使った機能の分だけ増えるのでしょうか
環境依存の話はスレチだけど、まるまる増えると思うよ。
仮想メモリはまるまる 物理メモリはコードについては使った分 データはシラネ
ありがとうございました 使いたいライブラリが8MBくらいあるもので、 まるまる増えるのはちょっとアレかな、と思って質問しました 改変可なので、必要な部分だけ取り出そうと思います
Managerクラスがあり その機能は、一部のクラス(と言っても10個ぐらいある><) にしか利用できないって設計の場合 一部のクラスをfriendする以外に何か方法はありませんか?
その一部のクラス以外はmanagerクラスのインスタンスを手に入れられないようにする。
>>180 freind じゃダメな理由を書いた方が答えが得られやすいと思う。
ミスった... orz freind ⇒ friend
friend先に依存が出来るからじゃね? 普通、friendは最終手段だし
そんなことはない。
friend 先に依存って何?
一部のクラスだけ特別扱いするというのがManagerクラスの仕様なら、 friendによる依存は妥当だと思う。
一部のクラスの基底クラスとして Manager を取得するクラスを作って、 その1つだけを friend にすれば?
189 :
180 :2008/03/23(日) 14:58:22
friendが結構な数になってしまうんです。 下手すれば私のリアルfriendより多いぐらい それが悔しくて
誰が上手い事を言えと
191 :
184 :2008/03/23(日) 15:01:24
俺は181に一票で
その方法を聞いてるんだろw
パスワード掛ければいいんじゃないですかね
w
権限プログラミングってのも面白そうじゃないか
singletonなら簡単なのにな
思い出したw ____ |← reject| boostの中の人 singleton ユーザー . ̄.|| ̄ ̄ ┗(^o^ )┳(`Д´)┳(^o^ )┛≡=- || ┏┗ ┗┗ ┏┗ ≡=-  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ユーザーは欲してると思うが
にわかに得た知識で面白いこと考えた! Managerのインスタンスを受け取る関数の引数に関数オブジェクトを使って 内部で一定のアルゴリズムで正しい値を返すもの(パスワードの暗号化みたいな)にのみそのインスタンスを渡してやる風にすればいいんじゃね? 更にインスタンスを受け取る関数をテンプレート化してやり、欲しい権限までのクラス型インスタンスを返すようにしてやればアクセス制限も出来て完璧! とここまで考えてわざわざこんなことしてもオーバーヘッドが大きいだけなことに気づいた そもそも何の意味があるんだっけか
201 :
デフォルトの名無しさん :2008/03/23(日) 16:57:35
Managerクラスコンストラクタなどをprotectedにして、使うクラスはManagerを継承する。
>>201 そう言うのは最悪。
あとから見て、継承が本当に必要だったのか、単に特定のメソッドを
使わせるために継承しているのかがわからなくなるから。
204 :
201 :2008/03/23(日) 17:21:39
>>203 意味がよく分からないけど、、、「特定にメソッドを使わせるために継承が必要かどうかがわからなくなる」ってこと?
そんなこと言ってたら何もできない。
friendだったら、なぜfriendにしたか分からなくならないの?
friend よりいいと思うけどな。
friend じゃprivateのメンバにアクセスできてしまう。
Managerクラスを機能を利用するんだから、継承しかないでしょ。
使う側のクラスに持たせるとなると、コンストラクタとかはpublicになってしまうし。
継承すると Managerの中のstaticでない変数とか勝手に作られない?
>>203 Manager クラスじゃなくて単に許可コントロール用の class を作る
というのは有りじゃない?そういう例をまともな本で見た記憶がある。
-カーズは- 2度と地球へは戻れなかった…。 鉱物と生物の中間の生命体となり 永遠に宇宙空間をさまようのだ。 そして死にたいと思っても死ねないので ―そのうちカーズは考えるのをやめた。 全部globalにすればいいじゃん
>>206 電波の缶詰の人のサンプルもそうだった
ライブラリ的なものを
外部からいじられないようにするためだったら
そんな感じでもいいんじゃまいか
村八分
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); } } };
それは、インスタンス取るのに時間かかるし friendでいいじゃんって話になるも
速度が重要なら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; }; 冗長だし検証してないけど。
Manager を使えるクラスを作成する場合には ファクトリクラスを通すようにする。 で、そのファクトリクラスを friend にして、 そこで Manager クラスを取得して、 各クラスにそれを渡すようにする。 設定関数は各クラスの共通基底クラスに作って、 それをファクトリクラスの friend にする。
先輩から聞いたのですが、extern "C" {}せずに構造体を宣言すると、 余計なクラス情報がくっつくって本当ですか?
そんなことは聞いた事が無いが、 特定のコンパイラでそういう事があるとかいうんだったら俺は知らない。
クラス情報って具体的には何なんだ?
>>213 マングリング名にクラス情報がくっつくって話だと思う。
>>214-216 言ってたのはシリコンバレー帰りの先輩です
純粋なCの構造体にするにはやはりextern "C"が必要なのですね。
ありがとうございました。
構造体にextern "C"は関係無いだろ
>>216 構造体名って C でそもそも何らかのマングリングされるの?
C++なら名前空間やらなんやらくっつくだろ。
C で付かないなら 純粋な C の構造体かどうかなんて どう区別するんだろうか。
>>204 まじめな話、もう一度継承についてちゃんと勉強した方がいいと思う。
(
>>205 の内容を理解できてる?)
継承はアクセス制限のためにあるものじゃない。
極端な話、全てが public であったとしても、継承は有用。
これに対して、friend は純粋にアクセス制限を回避するもので、かつ
アクセス制限を回避する以外の機能は無いから、なぜ friend にしたか
がわからなくなることはない。
(もちろん、なせアクセス制限を回避する必要があるかはどっかに書いて
おく必要があるだろうけど。)
>>206 それならアリだと思う。
224 :
201 :2008/03/23(日) 19:54:02
>>223 >>205 作られるけど。外から参照されたくないものはpublicにしなけらばいいじゃん
225 :
201 :2008/03/23(日) 20:00:37
>>223 >継承はアクセス制限のためにあるものじゃない。
>極端な話、全てが public であったとしても、継承は有用。
だから、継承が駄目なんですか?
継承は色んな意味で使えて「わかりにくい」から駄目ってこと?
何かもう駄目だなここって思ったの俺だけだろうか
Manager 使ってる部分を別プロジェクトにする。 あとは各クラスのオブジェクト生成を外部から隠せばいい。
>>224 > 作られるけど。外から参照されたくないものはpublicにしなけらばいいじゃん
おいおい、ほんとにもう少し勉強してからこいよ。
引っ込みつかなくなってるだけならいいけど、マジでそう思ってるとしたら
ちょっとまずいよ。
まずい理由の一つは、private でもその変数が見えなくなるわけじゃない、
アクセスできなくなるだけだから。
この違いわかってる?
>>225 > 継承は色んな意味で使えて「わかりにくい」から駄目ってこと?
>>203 に書いたのはそう言うこと。
それしか方法が無いならしょうがないけど、friend と言うもっといい方法があ
るのにわざわざ使わないのは、別の意図があるようにとられる危険性が高い。
229 :
201 :2008/03/23(日) 21:17:23
>>228 >マジでそう思ってるとしたらちょっとまずいよ。
Managerを継承していないクラスから参照されたくない場合はpublicにすれば良いって事だよ?
>まずい理由の一つは、private でもその変数が見えなくなるわけじゃない、
>アクセスできなくなるだけだから。
「見える」→メンバ変数の値が取得できる。(getter)
「アクセス」→メンバ変数の値が書きかえれる。(setter)
って意味で言ってるのなら
getter、setter定義してやれば、当然見えるしアクセスも可能。
もしかして201氏は、 Managerは1つのクライアント(Managerを使うクラスオブジェクト)の管理のみ引き受けるもので、 クライアントと同数のManagerオブジェクトが必要と考えているのではないだろうか。
>>229 > 「見える」→メンバ変数の値が取得できる。(getter)
> 「アクセス」→メンバ変数の値が書きかえれる。(setter)
ほら、全然理解できてない。
簡単な例でいうと、
int a, b;
class X {
private: int a;
};
class Y: public X {
int foo(){ return a; }
int bar(){ return b; }
};
ってやると、foo() の中で X::a をアクセスしようとするからエラーになるよね。
もし、C++ の private が変数を「見えなくする」なら bar() の b と同じように、
foo() は ::a を返すはずだろ?
これが、「見えなくなること」と「アクセスできなくなること」の違いなわけ。
これによる、影響は自分で調べてみてね。
>>230 まあ、それはそれでそれこそもっとよく考えろとしか言えないわけだが...
何でこんな残念なスレになってしまったんだ。
233 :
デフォルトの名無しさん :2008/03/23(日) 22:12:43
だって にちゃん だもの
VSyncの話したらひどいことになりそう
結局
>>182 って文句言ってるだけで答えて無いじゃん
答えは
>>188 で既にでてるだろ。
まあ、10個ぐらいなら全部 friend 宣言してもいいと思うけど。
もしかして君も
>>201 みたいに理解できてないやつなの? (w
>>188 だとManager::getInstanceみたいなので取得するのと大差無いと思うが・・・
まぁ、それはともかく、
>>180 にfriendなどを使ってまで
制限する必要性があるのか、疑問だな。
クラスごと使わせなくするとこにfriendを使用している時点でおかしいと思う。
無名名前空間やdetails名前空間で十分なんじゃないか?
239 :
201 :2008/03/23(日) 23:44:18
>>231 >foo() の中で X::a をアクセスしようとするからエラーになるよね。
アクセッサをManagerの方に定義することを考えていたんだけどな。
「見える」「見えない」の話じゃんくてprivateだからだろ。
>もし、C++ の private が変数を「見えなくする」なら bar() の b と同じように、
foo() は ::a を返すはずだろ?
グローバル変数よりメンバ変数を参照しにいくのは知ってます。
Managerの方に「一部のクラス」に使わせたい機能だけ、protected または public にして
一部のクラスがManagerを継承すればいい。
Manager のprivateのメンバには「一部のクラス」も参照できない。
「一部のクラス」以外にManagerクラスのインスタンスを作られるのが困る場合は
コンストラクタなどをprotectedにすればいいんでは?
「一部のクラス」に対してManagerは一つらしいので、また違ってきますが・・・・
これで friend いらない -- friends.cpp #include "A.h" #include "B.h" namespace { class Manager {}; Manger& manager(); } void A::f() { manager().a(); } void B::g() { manager().b(); }
>>238 > まぁ、それはともかく、
>>180 にfriendなどを使ってまで
> 制限する必要性があるのか、疑問だな。
それは、
>>180 に聞いてもらわないとダメだけど、そう言う状況はありえると思うよ。
例えば、デバッグのためにマネージャの状態を直接見たりいじったりするクラスとか。
ただ 10個もあるのは、ちょっと多すぎるような気はするけどね。
>>239 頼むから、もう少し勉強してからレスしてくれ。
全然俺の言ってることが理解できてないよ。
で、アホなのはどっちなの?初心者なのでよく分かりません
>>242 やり方は色々ある。って話に落ち着けていいんじゃないのw
メイヤーズもそんなことeffective c++に書いてたでしょ。
>>242 「そいつの中にあるもの」の質はともかく、
「そいつの中にあるものを説明する能力」はどっこいどっこいです。
245 :
デフォルトの名無しさん :2008/03/24(月) 17:47:39
仮想関数を持たないクラスXとクラスYがあります。 YはXを継承しています。これらのクラスに対応する インターフェイスのクラスIXとIYを以下のように定義しました。 しかし、コンパイルエラーでした。クラスYは抽象クラス とみなされたようです。でも、クラスYはf()の定義も g()の定義も持っているので抽象クラスではないように思えます。 XとYのインターフェイスを作る方法を教えて下さい。 class IX { virtual void f() = 0; }; class X : public IX { void f() {} }; class IY : public IX { virtual void g() = 0; }; class Y : public X, public IY { void g() {} }; int main() { Y y; // エラー(抽象クラスあるいは構造体のオブジェクトが宣言されています) return 0; }
IX IX ↑ ↑ X IY ↑↑ Y という継承木になっている。 X::IX::f は定義されているが、 IY::IX::f は定義されていない。 インタフェースクラスを作るなら、IX を仮想継承する必要がある。 ただ、それでも Y で f を定義する必要がある。 あと、インタフェースクラスに限らず、基底クラスには 必ず仮想デストラクタを定義するのを忘れないように。
247 :
デフォルトの名無しさん :2008/03/24(月) 18:14:09
>>246 ありがとうございます。
以下のように変更したらエラーが警告になりました。
この警告は無視していいような気がします。
>あと、インタフェースクラスに限らず、基底クラスには
>必ず仮想デストラクタを定義するのを忘れないように。
OKです。
class IX {
virtual void f() = 0;
};
class X : virtual public IX {
void f() {}
};
class IY : virtual public IX {
virtual void g() = 0;
};
class Y : public X, public IY {
void g() {}
};
int main()
{
Y y; // 警告('Y' : 2 つ以上のメンバが同じ名前を持っています。'X::f' から継承します。)
return 0;
}
Y::f では X::f と IY::f のどっちの実装を使えばいいのか分からないというもの。 まあ、今回の場合は IY::f に実装がないから X::f を使いますよという警告だけど、 Y に void f() { X::f(); } と書いておくのが無難。
class T { T( int ); } を T *T_array = new T [100]; は出来ないじゃん? #placement new使えってのはなしで。 std::vectorはどうやってこういうコンストラクタが引数を持ってるクラスを受け入れてるの?
placement newで
>>248 上の例では void f() 1個だけですが、実際のIXは純粋仮想関数を
22個もっています。Yに22個の関数をわざわざ定義するのはなんだか
無駄な気がするのですが。。。
>>251 まあ、面倒なら今のところは無視してもいいかもしれない。
コメントでも書いとこう。
>>241 頼むから、もう少しまともな説明してくれ。
>>252 わかりました。ありがとうございました。
friend 使うと「一部のクラス」が増えるとManagerも弄らないと駄目だな。
拡張性を敢えて犠牲にするなら、個別に friend するしかない。 拡張性もある程度考慮するなら基底クラス作ってそれだけ friend 。 あとは本人がどうしたいか、だな。
>>253 非常に初歩的な内容だし、あの説明で理解できないなら、
もうあきらめた方がいいぞ。
IDすら出ない板で煽り煽られ大変ですな
259 :
180 :2008/03/24(月) 23:04:33
私の為に喧嘩しないで><。
struct B{ struct P{ B *temp; } B( P p ){ swap( *this, *(p.temp) ); } operator P (){ P p; p.temp = this; return p; } }; B Return(){ return B(); } void Accept( B &b ){}; ------------ Accept( Return() ); //Error 俺、何間違えてるの?
設計?
262 :
デフォルトの名無しさん :2008/03/25(火) 00:07:13
エラーメッセージはキチンと書く
;
質問の仕方
Bにデフォルトコンストラクタないからとか?
Humanクラスを基底クラスとするTanakaやAsouやIshikawaクラスがあるとします Humanは抽象クラスとして用いるつもりです このときHumanにあるstaticメソッドを一回だけ呼び出したいときってどうすればいいでしょうか? Humanのコンストラクタで呼び出したとすると、TanakaやAsouのコンストラクタでも呼び出されますよね static bool initのような変数をフラグとして使う方法は思いついたのですが、 もっとスマートな方法はないのでしょうか?
シングルトンやそれに関わるC++の実装は非常に面倒くさくて 自分で一からやろうと思うとどうしても乱雑になる。 マルチスレッドが入ってくるともっと面倒くさくなる。
>>267 そのメソッドを呼び出したいのは、Human派生のオブジェクトを生成したタイミングなの?
271 :
267 :2008/03/25(火) 02:13:35
>>270 そうですね
Human派生のオブジェクトを生成する前に呼び出しても構わないのですが
>>271 であれば、全てが始まる前に自分で一度だけ呼ぶのが良いと思うな。
>>272 それはstaticな変数をフラグにするよりダメじゃねぇかw
274 :
267 :2008/03/25(火) 02:39:11
>>272 あぁそうか、そもそもstaticなメソッドなわけだから
int main(){
Human::onlyOnceCalled()
みたいなかんじで
最初の方で適当に呼んでおくってのもありかもしれませんね
一回だけしか呼ばないって保証がないような気もしますが
>>274 必ず最初に読んでしまってよいなら、クラスにスタティックなメンバを定義して
それの初期化の中で実行させてみては?
// human.h
class Human() {
// 中略
class Initializer { Initializer() { onlyOnceCalled(); } };
static Initializer init;
};
// human.cpp
Human::Initializer Human::init;
文法間違ってたらすまん
276 :
275 :2008/03/25(火) 02:51:47
Human::Initializerのコンストラクタがpublicになってないとか、いろいろダメだorz そこは適当におぎなって
277 :
267 :2008/03/25(火) 03:01:51
>>275 なるほど。こういう方法もあるんですね
勉強になりました
ありがとうございました
保証が欲しかったのか。失礼。 initialization orderを気にするならこんな感じかな。 class Human() { class Initializer { Initializer() { onlyOnceCalled(); } public: static void Initialize() { static Initializer instance; } }; }; これで、Initializer::Initializeを呼んだタイミングで一度だけ初期化されるようになるよ。ただしこの場合は複数スレッドとかが動き出す前に呼んでね。
279 :
260 :2008/03/25(火) 09:32:50
ぇ?コンパイル通る? gccだと通らないんだけど・・・
>>279 どこを見てそう思うんだよ・・・
指摘してくれてるだろ
>>263 >>266 あとAcceptがReturnの返す一時オブジェクトを参照してるから何とかしよう
>>279 まずは省略や手抜きをせずに、Bの定義を全部書け。
そして何をしたいのかはっきりさせろ。
282 :
260 :2008/03/25(火) 16:02:29
>>282 これで通った
struct B{
struct P{ B *temp; };
B(){}
B(P p){ swap( *this, *(p.temp) ); }
operator P () { P p; p.temp = this; return p; }
};
B Return(){ return B(); }
void Accept( B b ){};
int main(){ Accept( Return() ); }
参照渡しから値渡しに変更した理由が分からん
抽象クラスのメソッドの定義で質問があります 抽象クラスにおいて、自分自身のクラスへのポインタの引数を取るメソッドは不可能なのでしょうか? たとえばこういうコードです class Human { void foo(Human *human) = 0; }; コンパイルエラーになってしまいますが、なぜそうなるのか分かりません 抽象クラスだから、インスタンスを作れないので void (Human human); のようなメソッドはだめですよね、でもポインタならいけると思うのですが
B::operator P()の戻り値から構築されるBの一時オブジェクトは非const参照のAccept(B&)では受け取れないんじゃ?
その発送は無かったわ、thisポインタというものが(ry virtual書いてみたらどうかな?
一時変数を値渡しする理由は?const参照にしない理由が分からない。
289 :
285 :2008/03/25(火) 17:32:20
>>287 すいません元のコードではvirtualをつけてました
thisポインタは分かるのですが、この抽象クラスを継承したクラスの間でやりとりしたいことがあるのです
不勉強なので間違ってるかもしれませんが、「関連」というのをやりたいのです。
>>285 の例でやるなら、一般的にはHumanクラスにHuman *hoge;みたいなポインタをメンバに持たせて関連付けするそうですが
関数の引数でやれないかと思いまして
>>288 const参照でもいいかもしれないけど、それ以上所有権を動かせなくならない?
Acceptに入ってからも譲渡するなら、 void Accept(B& b) {} B b = Return(); Accept(b); の方が良くないかな、それ以前に何のためのPなんだ?
>>285 どういう一般的例なのかちょっと分からないけど、
処理と情報を分ける実装の方が個人的にはスッキリするかな
んで、そのプログラムvirtualつけてエラーが出る理由が分からないんだけど…
あぁ、失礼した、operator Pはconst守るようにしてるのね ごめん、俺が悪かった
294 :
292 :2008/03/25(火) 18:06:34
>>292 すいませんすごく単純なクラスを作り直し、実験してみると、エラーはでませんでした。
「抽象クラスをインスタンス化することができません」というエラーメッセージだったので、
質問させていただいたのですが、おそらく他のところにエラー.の原因があると思うのでもう一度見直してみます
295 :
294 :2008/03/25(火) 18:09:51
auto_ptrはauto_ptr_refクラスを介して対処している。 もう知っているかもしれないけど、 C++0xでは非const参照でも一時オブジェクトを受けられるようになる(右辺値参照)。
move semantics と rvalue reference &&
右辺値参照は何度もこのスレでも話されてるけど理解できん。
エラー出る出る言うなら、同じエラーが出る小さいプログラムを示せよ。 BやらPやらの例も、そもそもswapがないでコンパイル止まるしな。
右辺値及び左辺値(この二つは組)、参照の理解を固めてから見直すとよろし
>>298 簡単に言うと「swapでおk」ってこと。
302 :
260 :2008/03/25(火) 23:08:35
おなにーでさーせん。swapとかごめん。あと別に必要なかったかも。
コンパイル通った。
>>283 と一緒かな?
class D {
public:
struct Proxy { Proxy( D *d ):d_( d ){}; D *d_; };
operator struct Proxy () { return Proxy( this ); };
D( struct Proxy p ) {};
void operator = ( struct Proxy p ){};
D(){};
D( D &rhs ){};
void operator = ( D &rhs ){};
};
D Return() { return D(); }
int main( int, char** ){
D d = R();
return 0;
}
Accept( D &d );ってのは間違ってたかも。
ようは、
D( const D &rhs )だと、オーナーシップの移譲とかでrhsに変更加えられない。で、
D( D &rhs )だと、右辺値を渡せない。
だから、Proxyを返して、ごにょごにょする。って話なのか。
303 :
デフォルトの名無しさん :2008/03/27(木) 00:31:14
Cの関数ポインタにC++のClassの実体化した関数ていれられますか? ビルドエラーが出るんですけど、そもそもそんなの出来ない?
>>303 できない。
関数ポインタとメンバ関数ポインタは別物。
>>303 Windowsのコールバック関数みたいに
こっちから引数を渡せれば、どうにでもできる。
>>303 sizeofを使ってポインタサイズを調べてみると、あれびっくりサイズがデカイって分るよ。
どうやっても入りません、キャストしたら情報ロストします。
309 :
デフォルトの名無しさん :2008/03/27(木) 02:29:53
面倒だからboost::functionを調べてみ >303
311 :
デフォルトの名無しさん :2008/03/27(木) 02:56:20
詳しく説明した方がいいかと 要するに、メンバ関数ポインタがさす関数はvirtualである事もあって インスタンスに仕込まれた仮想テーブルを参照して、関数テーブルのうちどの位置にあるものかを取得する必要がある。 また、関数はvirtualでないケースもある、この場合仮想テーブルには関数のアドレス情報はないので、関数メンバポインタ内に情報がなければならない。 関数メンバポインタはこれら複合情報で構成された構造体となっている。
どこが詳しいのか
それなりに詳しいと思うけど、 であるがゆえに「要するに」から始まっているのは間違いだと思う。
>>303 関数ポインタには入れられないが、
実体とメンバ関数ポインタの対を構造体にしたものを引数に取る
ラッパ関数を通して呼ぶことはできる。
もちろん、C 側ではその構造体を直接扱うことはできないから、
void * を通すなり不完全型を利用してポインタで扱うなりする必要はあるけど。
>>309 >>305 はCのライブラリのコールバック使うときとかの対処法の話じゃね?
大抵はvoid*のパラメータ持ってるし。
virtual関係無いよね。
318 :
303 :2008/03/27(木) 08:50:26
やりたいのは複数newしたクラスからCの関数叩くんですけどその時の引数にコールバック用のCの関数ポインタがあるんです そしてその時呼んだ実体に関数ポインタによって帰ってくるようにしたいんです
引数を加えて、static関数で良いんじゃ?
>>317 非staticメンバ関数/インスタンスメソッドの事だとみんな理解してるよ。
>>318 コールバック関数のパラメタを汎用ポインタとかで指定できるなら、そこにオブジェクトのアドレスを入れて、コールバック関数内でキャストしてメンバ関数を呼ぶ。
パラメタを指定できないなら、コールバック関数から見えるスコープの変数にオブジェクトのアドレスを入れておき、コールバック関数からメンバ関数を呼ぶ。
クラスの関数ポインタはthisが略されてるようなもんじゃね
>>317 往生際が悪い、素直に自分の知識不足でしたと認めろ
static メンバ関数を C のコールバックに登録するのってよく見るし実際に やったこともあるんだけど、ほんとは extern "C" と extern "C++" の違いで 型が遭わないはずなんだよね。 だからって対応策がわかんないし、使ったことのあるコンパイラでは全部通るから そのまま使っちゃうんだけどさ。
>extern "C" と extern "C++" "C" とかの修飾は、識別子を外部にどういう規則で公開するかという点についての指定であって、スタックフレームの作り方の指定ではない。 機種依存なので、そっちにいけと事になるが、cdeclとpascalが違えば "C" を付加しても動作しない。 C型のスタックフレームを持つ関数として登録可能な関数なら、C型のコールバックに登録する事ができるという事。 そうでないなら、コンパイルが通ったとしてもうまくいかない。
>>325 スタックフレームとか実装に立ち入った話はしてない。言語概念上の型が違うんだよ。
知識不足は許容できるが嘘吐きになってはイカンぜよ
>>327-328 気持ちはわかる。きっとみんなこれらは同じものとして使ってるだろうし、
動作も問題ないだろうさ。
でも規格ではエラーにならないとダメなんだよ。はっきり書いてあるから。
7.5 "Linkage specifications" p1 より
> ... Two function types with different language linkages are distinct types even
> if they are otherwise identical.
gcc でもバグ扱いだ。
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316
>>329 自分を嘘と虚栄で塗り固めるような真似はやめた方がいい、どこに突っ込み入っているのかすら理解できていないだろ。
静的メンバ関数はextern "C++"ではない
328は327に宛てたもんだと俺は思った、どうでもいいけど。
333 :
329 :2008/03/27(木) 14:11:40
>>330 ごめん。どこに突っ込み入っているのかすら理解できてない。
どこが嘘になってるの?
>>331 何を根拠にそんなこと言うのか知らないけど、じゃぁ静的メンバ関数の
language linkage は "C++" 以外の何になるのさ?
虚言癖というか妄想癖というか・・・なんかもう病気だね(汗
>>334 静的メンバ関数のリンケージは内部リンケージで
その根拠は外部に公開されないから
逆にextern "C++"と同じという根拠は?
337 :
デフォルトの名無しさん :2008/03/27(木) 17:05:02
もうv(^・^)vの人はいないの?
ちゃんと勉強しろ、そんな高度な話題じゃねぇよ
コンストラクタの中で 配列宣言しているオブジェクトの コンストラクタ引数を設定するにはどうしたらいいですか?
class Test{ Test0 objects[10]; ... }; Test::Test() :objects[0]( 10 ) ,objects[1]( 8 ) ... { } こんなかんじをやりたいのです。 もちろん、これではエラーです
341 :
デフォルトの名無しさん :2008/03/27(木) 20:36:48
342 :
デフォルトの名無しさん :2008/03/27(木) 20:51:07
どうしてもそれっぽいことがやりたいなら vector<Test>にひとつひとつpush_back()するか ポインタの配列にしてひとつひとつnewすればいいんでないの
344 :
デフォルトの名無しさん :2008/03/27(木) 21:55:56
VC++6で for(int i=0; i<10; i++){ ... } for(int i=0; i<10; i++){ ... } って書いたら iの再定義っておこられた 拡張子cppになってるのに
仕様です
346 :
デフォルトの名無しさん :2008/03/27(木) 21:58:46
1998年発売のソフトやもん。
>>344 びっくりするくらいみんな知ってる。
規格準拠していないんだから何も問題ない。
>>344 #define for if(0); else for
魔法のおまじない
当時は準拠してたんだよ
まだ規格もなかったのに何に準拠してたというのか。
351 :
デフォルトの名無しさん :2008/03/27(木) 22:04:00
常識。
>324,329 だいたい、「関数ポインタ型」それ自体にはリンケージなんか無いだろ。 それともこーゆーコードが通るコンパイラでもあるのかっつーの。 typedef static void (*hoge)(); typedef extern void (*foo)(); typedef extern "C" void (*var)();
typedef void (*__stdcall type)(); こういうのならたまにやる。
それはリンケージじゃなくて呼び出し規約
>>356 forの中で定義した変数の有効範囲が
直後のループ本体に限られるようになったのは
結構遅かったのでは?D&Eでも軽く触れられていたし。
それに加え過去の互換性のためVC6はあれがデフォルトになったんだと思う。
昔の人が考えた仕様には、頭おかしいだろうってのがそれなりに有るからね。
初期のコンパイラの実装の都合もあったんじゃないかな? 最近のコンパイラで、forの変数の有効範囲が限られるようになってるのに最近気づいて思わずGJと叫んだ。
>>357 まあ 1998 年と言えば規格が出る年だしな。
開発期間とか考えると多少前の仕様に準じようとしてたと考えるのが妥当だけど、
その時期ならドラフトとはいえかなりな部分まで練られてると思うんだけどな。
まあ、想像でしかないので本当にギリギリになって入れられた仕様なのかもしんないけど。
VC6 はテンプレートまわりがバグ持ちすぎてかなり酷いが、
テンプレートも遅くに入った仕様だからな・・・。
new がデフォで bad_alloc 投げないとか、とにかく色々と酷い上に、
しばらく次のコンパイラが出なかったという・・・。
未だに古いライブラリとかで使わないといけないことが結構あるからねぇ VS2005から入った俺としては結構苦痛 まあでもテンプレートさえなければインテリセンス反映が早いのはよい
VC++6.0は当時の状況を考えればしょうがないと思う 問題なのは次のコンパイラがさっさと出なかった事 お陰で変に普及しちまって、このスレでもVC++6.0でコンパイルできません的な質問が絶えない
全てはMSが次期製品を確実に買ってくれる為に図った陰謀。
MSの事情的にはむしろ逆のような? 過去のシステムヘッダに, for で宣言した変数が その後も生きることに依存したコードがあったっていう……
#define for if(0) else for のおまじないと使ったあとでATLをincludeすると 怒られるちゅーか
>>363 そして満を持して登場した 2002 が糞だったという罠。
そして 2003 で大きく改善されるという二重の罠。
アカデミックだと無料アップグレードできないという三重の罠。
#define for if(0); else for は色々やった後にやるとよろし。
ってかincludeする前にundefするだろ・・・
>>336 ,352
ややこしくて嫌になるが、内部とか外部とかがある「リンケージ」と
"C" とか "C++" とかがある「言語リンケージ」("language linkage") とは
別物。 >324,329 が言ってるのは言語リンケージのほうなんで、話がまるで
かみ合ってない。
自信満々な
>>336 が可哀想に見えてきちゃったよw
逆にextern "C++"と同じという根拠は?ってのが哀愁をソソル
>>336 素の「リンケージ」の話だとしてもおかしい。静的メンバ関数のリンケージは
ほとんど外部リンケージになる。例外は関数内のクラスのメンバの場合とかね。
静的メンバ関数が「外部に公開されない」ってのもおかしいな。 クラスの宣言されたスコープや、クラス内での private なり public なりに 従うだろ、常考。
373 :
デフォルトの名無しさん :2008/03/28(金) 03:50:38
びやーんはもうC++なんか使っていないらしい。
ソースは?
2ch
>>372 public, privateと内部リンケージ, 外部リンケージはまた別の話だ
もう何がなんだかわからないよママン
>>359 もともとがCへのトランスレータだった事を考えれば自然に合点が行くね。
for( int i = 0 ; .... ) { ... }
変換後
{
int i ;
for( i = 0 ; .... ) { ... }
}
>>372 リンカなどの外部に公開され得るのはクラスであって内部リンケージであるメンバが同様に公開されているように見えるのは処理系の都合
>>380 クラスが外部リンケージを持つときに、メンバ関数が外部リンケージを持つかどうか は処理系依存だと言っているのならそれは違うよ
383 :
デフォルトの名無しさん :2008/03/30(日) 01:04:01
テンプレートをつかうと一気にコンパイル時間が10倍に?!
template使っても 型が1個と100個じゃ大違いだろ
このテンプレいつの間にか一つのレスにまとめられてたのかw
template <typename Questioner> int IsCompileTimeBecomeLongerByUsingTemplate() { return ENVIRONMENT_DEPENDENT; }
テンプレート無意味過ぎる
>>388 質問者に応じて別の回答をするように特殊化するんだよ。
template<> int IsCompileTimeBecomeLongerByUsingTemplate<教えて君>() { throw spoon(); }
匙は投げられた。
the biggest news of the meeting was that we voted lambda functions and closures into C++0x. // Writing a collection to cout, in C++0x: for_each( w.begin(), w.end(), []( const Widget& w ) { cout << w << " "; } );
スレ違い
LRESULT CALLBACKの関数をCLASSに所属させるにはどうすればできますか?
static
RTTIについて質問です。 RTTIありでオブジェクトファイルを生成したいが 外部libなどがRTTIを含んでいない場合は 自分側もそれにあわせてRTTIなしで組まなければ成らないのでしょうか?
コンパイラオプションでRTTIを使うかどうかの設定の話なら、ケースバイケース。 自分が知るVC++では、外部のオブジェクトに対してtypeidやdynamic_castをしなければ、 自プログラムがRTTI有効でも、問題なくリンクして実行できる。 逆にそうでない処理系も世の中あるかもしれない。
>>397 リンクでエラーが出たらオプション変えればいいんじゃないか?
>>400 普通にアクセスできるしスレ違いですさようなら
test
403 :
397 :2008/04/01(火) 02:34:57
>>398 環境依存てことですかね〜。
>>399 vcとのクロス開発あたりだとエラーがでてしまうのです;;
根本的になにをやりたいかというと、
シリアライズ機能を自前で実装しようと考えていまして
実装の際にRTTIのtypeidを利用して組むとらくそうなのですが・・・
ない場合はMFCやwxWidgetのようなクラス毎にマクロを仕組んで
独自の機構を作るしかないのかなって悩んでしまって・・
※boostのシリアライズという選択肢もありますが、boostが対応していない環境も考慮しました。
というか、例外・RTTI・CRTは、何も考えずに DLL超えとか、コンパイラ/オプションの違うlibを混ぜるとか するとハマるよ?
>>403 libのクラスをもう一度派生させたのを使ってみてはどうかな?
念のために聞くけど、そのlibをコンパイルしたコンパイラと使ってるコンパイラの種類とバージョンはあってる?
406 :
397 :2008/04/02(水) 04:43:48
>404 こちらはそこを懸念してるんですが、出来上がったものを使うのは私ではないのでなんとも・・・ >405 バージョンのほうはあってますが、こちらでつくったモジュールがどのようなケースで使用されるか をすべて網羅するわけにはいかないので・・ 派生というかstubのようなものをproxyとして使用する感じでしょうか? なんというか、それなりの状況でも使用に耐えうるもの、となると 結局RTTIははずさなければならないのかな、と思いました。
アクセスできるすべての識別子をリストアップするようなツールはないでしょうか。 class X { int i; public: int j; void f() {} }; というような場合に、 X X::j X::f() みたいに出力できるとうれしいのですが……。自分で字句解析するしかないかな。
doxygenいろいろ設定すれば出来るんじゃね?知らないけど。
>>407 他で散々話題になっているんだからここでまで張らなくていいよ。
>>408 doxygenで可能。privateは出てこない(設定で変えられるかも)
extern "C"しないで作られたshared libをcから呼ぶ方法ないでしょうか?
マングリング名がCの識別子として使えるならいけるかもね
C++ で C 用のラッパ関数作るといい。
ふつーにdlopenするとか。呼び出し規約が同じとは限らないけどw
gccxmlを使った他言語(pythonなど)への インターフェース自動生成ツールが最近でてきてるけど ちょっと複雑なコードだと自動生成に失敗するみたいだ まだ発展途上のツールだから仕方ないのか gccxmlに渡すオプションを考えればうまくいくのか どうなんでしょうか?
Exceptional C++ を読んでて、疑問点が出てきましたので質問します。 P173〜181 にかけての auto_ptr についての説明中に、 T* pt( new T(1) ); auto_ptr<T> pt( new T ); auto_ptr<T> a( source() ); ↑どう見ても関数呼び出しに見えるのですが、 初期化子と解釈しないとどうも前後の説明から辻褄が合いません。 ですが、手元にある数冊の参考書を調べてもググってみても 以上のような構文は「コンストラクタ初期化リスト」以外には見あたりませんでした。 これは関数呼び出しなのでしょうか?それとも初期化子なのでしょうか? もし、初期化子だとしたら、このような構文が出てきたときに どのようにして見分けたら良いのでしょうか? また、関数呼び出しのように見える初期化子の使い方についても よろしくご教示願います。
まさか<T>の部分を聞いてるのか?
int i = 0; int i(0); 上のふたつは等価、という話なのかな? typename identifier(typename, typename, ...); // プロトタイプ宣言 typename identifier(arg1, arg2, ...); // 初期化 identifier(arg1, arg2, ...); // 関数呼び出し ただし、C++では、関数宣言として解析できるものは関数宣言と見なすので、 list<int> data(istream_iterator<int>(cin), istream_iterator<int>()); は(cinの内容で初期化したlistの宣言ではなく)関数宣言になる。
typedef typelist< char, 1, 2, 3, bool > LIST; なんてことは出来ないですかね?
boost::mpl, boost::tuple, boost::fusion辺り?
>>418 読むだけじゃなくていろいろ試してみたら?
classメンバを外部からリードオンリーに出来ませんか? 全部のメンバにゲッタを設定するのも面倒ですし
>>418 その本持ってるが、その部分に間違いはない。
auto_ptrのメンバ関数のインターフェース見れば疑問は無くなるはず。
>>424 class A{
public:
int aho;
};
const A baka; //全部リードオンリーなクラス
>>424 必要になるまでゲッタなんて書かなきゃいい。
constなんてダサい。時代はreadonly。
extern "C" { struct B : public A {}; } ができた. class AのデータだけにはCからアクセスできるのかも methodは無理か?
extern "C" は変数と関数にしか意味がないからな。
>>424 class A {
int member_prv;
public:
const int & member;
A() : member(member_prv) {}
}
まあ何だ、C++にはReadOnlyなプロパティを書く構文的な補助がないから、素直にgetter書いとけ。
漏れはこんなマクロを書いた。 #define readonly(TYPE, ID)\ public: TYPE ID() const { return _##ID; }\ private: TYPE _##ID class C { readonly(int, priv); readonly(unsigned int, b1) : 16; readonly(unsigned int, b2) : 16; public: C() {} };
435 :
デフォルトの名無しさん :2008/04/08(火) 17:57:59
キーワードtypenameの意味が分かりません。テンプレートを定義するときに よく使われるようですが、なくても良いような気がします。例えば、 プログラミング言語C++のp.599にある bind2nd の定義のtypenameを取って コンパイルしてみましたが、コンパイルが通って、テストコードがきちんと 動きました。typenameの存在意義を教えていただけないでしょうか。 こういう場合にtypenameがなければ困るという分かりやすい例が欲しいです。 // ----- プログラミング言語C++(p.599)より ----- template <class BinOp> class my_binder2nd : public unary_function<BinOp::first_argument_type, BinOp::result_type> { // my_を付けて実験 protected: BinOp op; typename BinOp::second_argument_type arg2; // このtypenameを取ってみた。 public: my_binder2nd(const BinOp& x, const typename BinOp::second_argument_type& v) // このtypenameも取った。 : op(x), arg2(v) {} result_type operator()(const argument_type& x) const { return op(x, arg2); } }; template<class BinOp, class T> my_binder2nd<BinOp> my_bind2nd(const BinOp& op, const T& v) { return my_binder2nd<BinOp>(op, v);
C++FAQにありそうなネタだな
コンパイラの迷いを断ち切るためにあります
>>436 なるほど、理解できました。でもコンパイラが十分賢ければtypenameは不要だと
言えそうですね。コンパイラはテンプレートの解析時においては typename
を付けていない T::something が型かどうか分かりませんが、実際にコードを
生成するときには分かるので、本質的には曖昧さの問題はないように思えます。
移植性を考慮するなら付けておけばいい。
441 :
デフォルトの名無しさん :2008/04/09(水) 15:23:39
別のファイルで定義した変数を使うにはどうしたらいいんでしょう? プログラムの改変を行っているのですが、前任者が作業ごとにファイルをわけています。 AAA.cppみたいなのがいっぱいあります。ヘッダファイルも同じ名前でたくさんあります。
VC++ってもうやばくないですか? 今やVBC#でもms単位で計測しないと実行速度違いがわからないぐらいですし 出来ないこともないですよね
>>443 場合によりけり
あと、その話題はこのスレ向きじゃない
>>443 んな事ないよ
OpenGL Viewerが前回のバージョンから恐らくC#になったんだと
思うが、やはり動作がもさもさする。
>>443 ゲームとかms単位が命取り
ms以下単位だったら考えてやる
μに縮まったとしてもまだでかいだろ。
数値計算とかやったことないんだろうなあ。
>>441 そういうファイル構成はC++では一般的。
その同名のヘッダーを読み込みば、十分アクセスできるはず。その前任者のソースをよく読んでC++を勉強すること。
C++はexternを滅多に使わないからね。
XBOX360のゲームは全部C#で書かれてるだろ
>>439 T::something が型でも値でもコンパイルできてしまう場合は困るでしょう?
多分どちらかは間違っているんだから
>>450 んなわけないだろ
プロがXNAで開発してるとでも思ってるのか?
思ったw
.netフレームワークを要求する商用アプリで動きが機敏なアプリをいまだかつて見たことないな。
多言語からc++を呼ぶインターフェイスで std::cout がおかしくなる原因になってるらしくなんとかしたい #define __streambuf なにか にできればいいのだけど voidに置き換えるとコンパイルとおらない 何か適当なクラスでもないでしょうか?
ios::sync_with_stdio で解決されるような問題じゃなくて?
458 :
456 :2008/04/10(木) 00:12:16
他言語の処理系がstdcoutをすでにリンクしているのに さらにその処理系から呼び出すcのプログラム中でもリンクしてるのが 問題なってる可能性があるような気がしています なので #define __streambuf Hoge できると多分うまくいくのではないかと
XNAなめんな
>>456 多言語から呼び出すってっ、もしかすると他言語からDLL呼び出しすることってことかな?
だったらライブラリの初期化がうまく言ってないんじゃないか?dllmainはこねこねした?
あと、DLLはマルチスレッドライブラリでコンパイルだよ。
462 :
456 :2008/04/10(木) 00:24:19
>>460 正確にはlibhoge.soを呼んでます
libhoge.soがstd::stream関係をリンクしてます
463 :
460 :2008/04/10(木) 00:27:49
linuxでしたか。
>>460 はwinの場合の注意事項でした。
>>461 MTでコンパイルしないといけない決まりでもあるの?
>>464 ある。
DLLをコンパイルするときはMTでする必要がある。プロジェクトの作成でDLLを選択すると自動的にマルチスレッドランタイムライブラリが選択される。
呼ぶ側はどっちでもいい。
>>465 何の処理系の話か知らないがVisualC++なら
シングルスレッドのランタイムの静的ライブラリをリンクしたシングルスレッド専用のDLLを普通に作れる
端で見てて想像した通りの食い違い方w
初歩的な質問で申し訳ないんだが、他言語から C++ の ライブラリを使って問題無いはず、という保証はあるんだろうか? あと、普通に C++ で呼び出すとかなぜしないのだろうか。 (これは状況がわからんとなんとも言えないけど)
operator==() の定義はクラスの中とクラスの外に置けますがどのように 使い分けるのでしょうか? std::type_info はクラスの中でその他はクラスの外が多いのですが。
470 :
デフォルトの名無しさん :2008/04/10(木) 15:34:04
別にoperator==()に限らずメンバ関数は中にも外にも置けるけど。
ププ
ペペ
== どうするかは状況によるんでは。無理無く member にしないで いいならそうすればいいような気がするが。中身の情報が必要な 場合に member にしてるんじゃないの?普通に生じる状況だと思うけど。
メンバに出来るものは中に書く。 メンバに出来ないものは外に書く。 以上。
475 :
デフォルトの名無しさん :2008/04/10(木) 18:05:52
c++のエラー出力の文字コードがutf-8になっているのですが、 euc-jpにする方法ありますか? Linuxのeuc-jp環境でプログラミング行っており、 gcc version 4.1.2 です。
iconv
ロケール切り替えろとしか
public 関数だけで実装できる場合は非メンバーにする。 friend を使って非メンバーにすることもある。
式の対称性が必要なら非メンバー
自身への参照を返すことが期待されるか、自身を変更する場合は、メンバーにすることが漏れは多いな。 operator=, +=等はメンバに。operator==, <<, +等は非メンバ(場合によってはfriend)にしてる。
op == あたりの話はeffective C++に書いてなかった? もう忘れちゃったけど。 グローバルにop ==を置くことでカプセル化が上がるとか その話とはまた別?
friend はできれば避けた方が良いというの無かったっけ?
C++ Coding Standards の 44 には 「できるだけ非メンバーかつ非 friend の関数を書くようにしよう」 というのがありました。
C++の本質はやっぱプリプロセッサとテンプレートだろ・・・ オブジェクト指向なんてうんこ
プリプロセッサはちょっと違うだろ・・・ 現実的にメタプログラミングするのには必要だけど。 個人的にはデストラクタを推すね。 2行目は同意。
デストラクタとはいいところをつくね。 RAII 万歳!
487 :
デフォルトの名無しさん :2008/04/10(木) 23:25:35
friendかな
デストラクタの価値が分からないうちは プログラマの資格なしだぜ
490 :
485 :2008/04/11(金) 00:03:01
>>488 ID出ない板だからどうしようも無いけど、
違うとだけ。
デストラクタはクリティカルセクション解除するのに使ってる。 メモリリークどころの騒ぎじゃない
Javaとかどーやってんだ? デストラクタ
Javaはcloseとかdisposeとかメソッド作って 呼び出さないといけないんじゃなかったっけ?
Javaはデストラクタ勝手に作ってくれるから。 DB接続とかファイルハンドルにクリティカルセクションだの なんでも閉じてくれる。
前スレから
http://pc11.2ch.net/test/read.cgi/tech/1200044614/496- 496 :デフォルトの名無しさん [sage] :2008/02/15(金) 14:44:30
つまるところc++ではデストラクタに頼るべき。
497 :デフォルトの名無しさん [sage] :2008/02/15(金) 14:54:04
C++はつまるところデストラクタのことだからな
closeさせといてガベージコレクタがあるとか抜かす言語は笑えるな
intは回収できるが巨大なファイルリソースはリークするわけだ
498 :デフォルトの名無しさん [sage] :2008/02/15(金) 15:06:22
日本語でおk
499 :デフォルトの名無しさん [sage] :2008/02/15(金) 15:08:34
>closeさせといてガベージコレクタがあるとか
禿げあがる程同意。
C#はusing(o1,o2,...){}があるから多少マシだけど、
forみたいにusing用のスコープ作るから
スコープ違いが混じるとネストして見辛くなる。
どう考えてもc++みたいに対象の変数のスコープでDisposeした方が良いと思う。
javaのtry-finally-closeに至っては論外。
しかもcloseで例外出たらfinally内で潰さないと
try内で発生したより重要な例外が消されるし・・・。
500 :デフォルトの名無しさん [sage] :2008/02/15(金) 16:33:04
>どう考えてもc++みたいに対象の変数のスコープでDisposeした方が良いと思う。
そして言語はC++/CLIへと進化するのであった、まる
Javaをはじめ、メジャーな言語のGCはメモリ不足しか認識しないから、 明示的にcloseしない場合、メモリに余裕があればfinalizeは呼ばれず、 DB接続も閉じられない そしてコネクションプールのタイムアウトで死に始める業務アプリ 鳴り始めるサポートデスクの電話機達
まぁJavaなんてマーケット戦略で広まっただけのうんこ言語だからな・・・ プログラマと名乗るくらいならC++くらいできる頭を持って欲しい・・
finalize()でリソース解放なんて保険でしかないからな
でもね、C++は巨大で複雑怪奇だからね。Cを引きずってる面もあるし。 無駄を削ぎ落として細部を明確にした言語が望まれるというのもわかるよ。 それとGCの有用性とは別の話だが。
実はVBなんかも リソース周りは優秀だったりする
continuationを明示的に扱えない言語はうんこ
scheme習いたてですか?
C#のusingの使いづらさは異常 scopedとでもして識別子が入ってるブロックの最後でdisposeしてくれたほうがよかった
素朴な疑問です。 #include <iostream> struct S { virtual void hoge() = 0; // 純粋仮想のみ }; struct S1 : public S { void hoge() { std::cout << "S1" << std::endl; }}; struct S2 : public S { void hoge() { std::cout << "S2" << std::endl; }}; int main() { S1 s1; S2 s2; S& r1 = s1; S& r2 = s2; r1.hoge(); r2.hoge(); r1 = r2; // 基本クラスの参照を代入 r1.hoge(); r2.hoge(); return 0; } VC8で上記のコードを実行すると S1 S2 S1 S2 と表示されました。 r1 = r2;はS::operator=を呼ぶだけなので何も変わらない、と理解したのですが、 これはC++的に正しい挙動なのでしょうか? それとも未定義でたまたまこうなっているだけなのでしょうか?
あ、改行を削ったらコメントをミスりました。 > struct S { virtual void hoge() = 0; // 純粋仮想のみ }; は > struct S { virtual void hoge() = 0; /* 純粋仮想のみ */ }; です。
単純に、自動生成されたoperator=(S, S)で仮想関数テーブルが書き換わらないようになってるだけ。
s1, s2のうちSの部分だけがコピーされた、と解釈すればわからんでもない
とりあえず解決するには自分でS2 operator=(S, S)を定義すればいいように思えるが、 それはS = Sの一般的な代入に関して考えるとかなり狂っているから諦めろって言う話でっていう
>>498 同意。finalizeって呼ばれるとは限らないとか。ほんとに気休め程度だね。
>>506 代入や他オブジェクトでの初期化でvptrは変更されない。
class A { friend class B; int x; }; class B { class C {}; }; VC8.0 では class C から class A の x が参照できますがこれは C++ の仕様ですか?
Cのreadableなプログラムを自動生成するメタ言語みたいなの ないでしょうか? readableじゃないのならあるのですが、読めないと意味ないのです
具体例を。
まともなCソースも
>>514 には、readable じゃなさそうだ...。
vector<int>で何個か反復子を進めたあと、 それが今何番目の要素なのかを知る関数はないですか?
i - v.begin();
できました、ありがとうございます。
だから何だよ
優れているというかパフォーマンスを犠牲にしてリソース管理の安全性を高めたという方が近いかな。 そんな事いったらC++も保守性を犠牲にパフォーマンスを高める余地のある言語と言えるけど。 ただJavaの場合は“余地”どころかプログラマに選択をさせない完全な“切捨て”であるけどね。 だからプログラマが手段を選択できる余地の残っているC++の方が優れている。終了。
手段を選択する必要のある場面においては、だけどな。
javaってfinallyの書き方間違えると死ねるしなあ
という話が
>>495 にあるよ
jdbcでoracle使ったことがある人は知ってると思うけど、
closeし損ねるとリークしてそのうち動かなくなるんだよね
これを注意深く追ってると、「なんだかCでやってんのと変わらんなあ」
と思うぜ、実際。
だってメモリしか管理してくれないもの
>521 「RAIIが発明されるまでのC++」については、Javaのほうが リソース管理が優れていた、と云わざるを得ない、けどねぇ。
他のリソースも管理してくれればいいのになあ。 ファイルハンドルが足りない時には ファイルクラスのインスタンスへのガベコレを 優先的にやってくれるとか。
>>527 > 「RAIIが発明されるまでのC++」
って具体的に何を指すの? RAII ってプログラミング
ポリシーだと思うんだけど。「発明」されたっていまいちピンと来ない。
RAII が浸透してない C++ って感じのことを言いたいんじゃないか? 未だに RAII を取り入れない C++ があるとは信じられないのかもしれないが。
javaの話だろ
>>527 C with class の話ですか?
C++は初期のARMがかかれた頃から散々言われていますけど。
>>529 強いて言えば、テンプレートがなかった頃には、
auto_ptrや(削除子付きの)boost::shared_ptrのような
汎用的なものは作りづらかったと思う。
それでも、fstreamみたいに個別に作っていく手があったはずだけど。
なんでそこで糞設計のstreamを持ち出すかなー
とりあえずデストラクタでcloseしてくれるからいいだろ。 今は糞設計かどうかなんて関係ない。
自分のクラスにiteratorをアタッチ するにはどうすればよいの?
>>537 クラスって新しい container 作ってんの?
普通に vector とかにオブジェクト入れて iterator 使うとかいう話
じゃないんだよね?
Rubyみたいにアタッチしたいんだけど なんでできないの?
だからアタッチって何だよ
ウラララララーって叫ぶやつじゃね?
それは、アパッチ
だってオラは人間だから
テンプレートクラスとクラステンプレートの違いを教えてエロい人!!
クラステンプレートを使って作られたクラスがテンプレートクラス
何か詳しく書かれたサイトがあれば貼っていただきたいです。
お前誰だよ
つーか言葉にこだわってどーすんの テンプレート勉強すりゃわかることだろうに
ヒントがあれば十分だろ。 自分で考えて解決する楽しさを知らないやつは(ry
552 :
551 :2008/04/15(火) 22:33:53
553 :
デフォルトの名無しさん :2008/04/15(火) 22:36:31
輪講で必要なんです。 わかりにくかったので聞いてみました。
>>552 流れとしてはわりと的を射ている気がするw
テンプレートクラスはただの間違いだと思う クラステンプレートが正しい。だってあれはテンプレートだから クラステンプレートをテンプレートクラスというのは 鉄パイプをパイプ鉄というようなもの
>>555 さん
わかりやすい表現ありがとうございます。
教科書には
クラステンプレートはテンプレートクラスから導出できる。
クラステンプレートは非テンプレートクラスから導出できる。
テンプレートクラスはクラステンプレートから導出できる。
非テンプレートクラスはクラステンプレートから導出できる。
と書いてあるのですが・・・
まずは本の名前を晒してみれ。
なんの哲学書だよw
こんにゃくゼリーに使うこんにゃくをゼリーこんにゃくって呼んでる類だろ。
ソースで出てくる順がtemplate classだから間違えやすいな
typename
STLに boost::any相当のものってないよね? 困った困った
普通にboost::any使ったら?
vectorにデータを追加した時にメモリ確保に失敗した場合、検出する方法ってありませんか? newでいうbad_allocの例外をキャッチするような感じ。
566 :
565 :2008/04/16(水) 02:26:50
解決しました。orz bad_alloc使えた...
>>563 無いなら作れば?
大したもんでもないっしょ。
568 :
デフォルトの名無しさん :2008/04/16(水) 13:24:51
あるアクションゲームをCとC++両方で作りました。 プレイする上で、まったく同じ動作をするものです。 Cでは主に構造体で、C++ではVectorで管理していました。 C++で作ったほうがプログラム実行時のメモリ消費量が多いのですが、 そんなもんでしょうか?
そんなもん 完全に同一ソースでもバイナリレベルでは例外処理が入ったり、実行時型判定が入ったりする
>>568 Vector は std::vector のこと?
そうなると構造体と std::vector とでは役割が違うので、置き換えれるわけ無いんだけど。
・・・もしかして
struct S { int a, b, c } s;
s.a = s.b + s.c;
これを
std::vector<int> s(3);
s[0] = s[1] + s[2];
にしたってこと?
まぁプログラムが違うんならメモリ消費量が違うのはあたりまえなんで、
あんまり気にしてもしょうがないと思う。同じになるはずっていう根拠でもなければ。
配列のことを構造体といい間違えたのではないか。
572 :
568 :2008/04/16(水) 14:33:50
配列ですね、すみません。 消費メモリが数十MByte単位で変わってくると、さすがに気になったので質問しました。 C++の設計に改善点がまだあるような気もします。
数十MBって、それってC/C++以前にプログラムの構造がおかしいだろ常考
> C++で作ったほうがプログラム実行時のメモリ消費量が多いのですが、 これだけ読んだら、普通はもうちょっとささやかな差を想像するよね。 その想像をベースにして皆が一般的なことを回答したところで、いきなり > 消費メモリが数十MByte単位で変わってくると、 っていう、量に関する新情報を出すっていうのは、広義の「情報小出し質問」だと思うよ。 自分だけが知っている状況を他人に説明するときは、発信する前に 「相手はこの説明に触れて、真っ先にどんなものを想像するだろうか?」 っていう思考を巡らせるべき。 で回答だけど、「構造体とvector」以外に両者のソースがどう違ってるかがわからないと、何とも言えない。 質問文に登場した要素だけで考えるなら、STLの使い方をどこかで根本的に間違えているんじゃないか って気がするけども。
前方反復子のクラスはデフォルトコンストラクタが必要ですけど、 デフォルトコンストラクタで生成した反復子やそれを代入した 反復子に対する操作の結果は定義されているでしょうか?
詳しく読んでないからわからんが、派生クラスで基底クラスのデストラクタが呼び出されないとかなら virtualが抜けてるからとかそんなんじゃね?
578 :
デフォルトの名無しさん :2008/04/16(水) 20:51:17
まだ始めたばかりの初心者です。。 あまりを出さなくてよい、簡単な割り勘のようなのを作っているのですが、 - #include<stdio.h> int main(void) { int a,b,c; /*計算の入力 金額*/ printf("金額を入力してください"); scanf("d%",&a); /*人数*/ printf("人数を入力してください"); scanf("%d",&b); /*計算と結果の表示*/ c=a/b; printf("%d/%d=\t%d\n",a,b,c); return 0; } - これを実行させると、金額を入力してEnterキーを押した時点で変な数字が出てきてしまいます… なにか足りない気がしますが、何処がおかしいのでしょうか…? ご教授よろしくお願いします。
どのコードを書いて、どういうメッセージは出たのか、 情報が足りなさ過ぎる。
scanf("d%",&a); 打ち間違い?
583 :
576 :2008/04/16(水) 21:15:39
>>580 スミマセン。。。
//dest_sample.cppのコードをまるっきりそのまま書いて実行したところ、
実行結果例の下2行の「消滅しました」のつく文だけ表示されません。
問題なくコンパイルできますし、上4行の「生成されました」と「呼び出されました」
の付く文は正常に表示されます。
試しに、筆者が書いたものをコピー&ペーストして実行してみましたが、
やはり「消滅しました」のつく、下2行の文が表示されません。
~Nanika(){
cout << "Nanikaのインスタンス" << datum << "が消滅しました。" << endl;
が完全に無視されているような状態です。
宜しくお願いします。
コンパイラは何?
585 :
デフォルトの名無しさん :2008/04/16(水) 21:39:59
namespaceにはまっています。 あるソースファイルのnamespaceで囲まれた関数を別のソースファイルでexternしたいのですが、 どうすればいいかわかりません。コンパイルエラーになります。 名前空間名を付けて呼び出してもだめで・・・。 aaa.cpp----------------------------------- #include <stdio.h> namespace hoge { void Func() { printf("HELLO\n"); return 0; } } bbb.cpp------------------------------------ extern void hoge::Func(); ←コンパイルエラー void main() { hoge::Func() ← コンパイルエラー Func(); ← コンパイルエラー return; } ----------------------------------------- bbb.cppからaaa.cppの名前空間が見えてないっぽいんですがこんな場合どうしたらいいのかわかりません。 ネットでも検索したのですが、複数ファイルに分ける事ができる記述はあっても やり方が乗ってないので困ってます。どなたかお願いします。
namespace hoge{ extereeeen void Func(); }
namespace hoge { void Func(); } int main() { hoge::Func(); }
ああ、コンパイラはVC++2008EEか。
589 :
デフォルトの名無しさん :2008/04/16(水) 22:00:46
>>586 bbb.cppでexternする場合はコレもnamespaceで囲んであげないといけないと言うことでしょうか!?
やってみたのですがVC++6.0なせいか hogeがシンタックスエラーを起こしてます。
VC++対応していない?明日会社でやってみます。
>>587 586さんと似てるのですが、externしなくてもよいと言うことでしょうか?
これまたVC++6.0ではhogeがシンタックエラーを起こしています。
明日やってみます。
VC6 でも問題はないはずなんだが・・・
関数プロトタイプはデフォルトで extern ってのは常識だろ?
>>583 VC++2008でやってみたけど、ちゃんと表示されたよ。
ひょっとしてNanikaのインスタンスを グローバルで生成したというオチではないだろうなw
外部ライブラリのデストラクタの方が後に走るから グローバル変数にしても cout に問題はないと思う。 というか、グローバルにしても表示された。
#include <boost/regex.hpp> template<typename TChar> class TCHoge { public: typedef boost::basic_regex<TChar> regex_type; static int Func(regex_type reg){ return 0; }//ok //static int Func(regex_type::flag_type flag){ return 0; } // NG1 //static int Func(boost::basic_regex<TChar>::flag_type flag){ return 0; } // NG2 static int Func2(boost::basic_regex<char>::flag_type flag){ return 0; } //OK }; Window2000 Visual C++ 2005 express edition boost 1.34.1 NG1 のように記述したいのですが,以下のようなエラーとなってしまいます. warning C4346: 'boost::basic_regex<charT>::flag_type' : 依存名は型ではありません。 error C2061: 構文エラー : 識別子 'flag_type' VC6.0 では問題なかったのですが,どのように記述すれば良いでしょうか?
×boost::basic_regex<TChar>::flag_type ○typename boost::basic_regex<TChar>::flag_type だっけ?あまり自信ないや
597 :
595 :2008/04/17(木) 03:25:08
>>596 さん,有難う御座います.教えていただいた方法でうまくいきました.
これから typename をつけまくる作業に戻ります…
それでは.
>>575 基本的には全部未定義。唯一、デフォルトコンストラクタで初期化したイテレータに、
そうではない値を代入することができる、ってことになるみたい。
24.1p5 の "Iterators can also have singular values ..." あたりにそんなことが
書いてあって、デフォルトコンストラクタで作った Forward iterator は singular value を
持つ(ことがある)とされている。
要するに未初期化のポインタやヌルポインタと同じ扱いってことね。
>>597 VC6 だと逆にエラーになるから
もし VC6 でもコンパイルしたいということになりそうなら
後で切り替えられるようにマクロにしといた方がいい。
VC6を窓から捨てるのが正解かと boostでもVC6は切ってるし
>>589 プロトタイプ宣言したヘッダファイルを作れ。
つーか、チミのやりかたではnamespaceつくらなくてもアウチなんだけど
stlやboostを使っていると、typedefを書く場所に悩みます。 class ClassA { HogePtr pHoge_; }; class ClassB { HogePtr pHoge_; }; この時、typedef boost::shared_ptr<Hoge> HogePtr;はどこに書くのが理にかなっているのでしょうか? Hoge.h?それともClassA.hとClassB.h?
>>602 typedef しないという選択肢は無いのかね?
ほんとに HogePtr に意味があるなら Hoge.h だろうね。
604 :
602 :2008/04/17(木) 13:00:36
>>603 すみませんtypedefしない選択肢もありました。
Hoge.hでtypedefするか、typedefしないかの2択ですね。
ありがとうございました。
class Hoge { public: typedef boost::shared_ptr<Hoge> ptr_t; }; というのはどうですか?
606 :
デフォルトの名無しさん :2008/04/17(木) 23:27:03
ClassA や ClassB の実装部分を HogePtr の実体から分離するために typedef 名をつかうってんなら、いっそ template class <T> class ClassAImpl { typedef boost::shared_ptr<T> Ptr; ... }; で、 typedef ClassAImpl<Hoge> ClassA; あたりまでやっちゃうのも悪くないと思うよ。
inline std::string Reverse( const std::string & src ){ return std::string( src.rbegin( ), std::rend( ) ); } これくらいシンプルな感じで実装する方法ないですか?
ようするに逆順でイテレーションしたいんだろうさ
実装する手間を惜しんでシンプルな設計を考えることは良いことだが、 人に説明する手間を惜しむのは(・A・)イクナイ!!
>>608 すいません。
>>609 ってことです。しかもstd::rend( )って何だよ・・・orz
当然できんだろ、って思ってたらコンパイルエラーになるんすね。
やっぱcopy使うのが一番まともでしょうか?
612 :
602 :2008/04/18(金) 01:45:35
>>605 なるほど、それもありましたか。
>>606 ClassAとHogeの分離は考えてなかったです。
考えていたのは、
1、クラステンプレート実体化のコードが長くなるので、stlやboostはtypedefして使うものだと思っていた。
2、shared_ptrを使うという事は、2つ以上のクラス(スコープ)で型を使う事になるので、typedefを1箇所(Hoge.h)にだけ書いて、参照したほうがいいのではないか?
3、しかし、shared_ptrに入れて使うかどうかは、Hoge.hをインクルードして使う側の選択肢であって、使う側の可能性をHoge.hに書いてしまうのはどうか?
といったことで悩んでいました。
>>611 よくわからんが std::reverse でも使っとけ
世の中にはある程度の割り切りが必要な時だってあるのさ・・・
>>611 make_reverse_range(src) // boost::range_ex
src|reversed // pstade::oven
非標準のライブラリ使ってもいいならこんな感じで簡単に書ける
>>612 HogePtrをtemplateにして
template template parameterでboost::shared_ptr等を与える
// hoge.h
struct Hoge { ... };
template< template<typename T> class Pointer >
struct HogePtr {
typedef Pointer<Hoge> type;
};
// client code
#include "hoge.h"
template< typename T > struct raw_pointer { typedef T *type; };
HogePtr<raw_ptr> raw;
#include <boost/shared_ptr.hpp>
HogePtr<boost::shared_ptr> shared;
これならhoge.hppで#includeしなくてもよくなる筈
>>615 ×HogePtr<raw_ptr> raw;
○HogePtr<raw_ptr>::type::type raw;
×HogePtr<boost::shared_ptr> shared;
○HogePtr<boost::shared_ptr>::type shared;
ではなくて?
そもそもhoge.hppでshared_ptr.hppの#includeを避けるなら
// client code
Hoge* raw;
boost::shared_ptr<Hoge> shared;
でいいじゃん?
>>581 >>582 返信遅くなってしまいました…
そんな単純なミスだったんですね…
ありがとうございました。
ベースメンバ初期化で"this"を使用すると警告がでますが、 コンストラクタ内で"this"を使っても警告も何も出ないけど大丈夫なんですか? 警告が出てるのはインスタンスが生成されていることが保証されて無い状態で そのポインタを読んでいることが原因になっていると考えているのですが、 だとすると、コンストラクタ内で使っても同じことですよね。 警告が出ないのは、そのポインタの先を使用しなければおkって事なんですかね・・。
コンストラクタ内ではメンバの実体は既に生成されているから問題ない どんな値がはいってるかは知らないけどね
620 :
618 :2008/04/19(土) 15:58:08
>>619 >>コンストラクタ内ではメンバの実体は既に生成されているから問題ない
なのに
>>どんな値がはいってるかは知らないけどね
とは?
実体は生成されているけど、thisが指しているのはどこか分からないよ
ってことですか?
それとも、実体の中身に何が入っているか分からないよってことですか?
ポインタの先を使用しなけりゃ大丈夫。
622 :
618 :2008/04/19(土) 16:12:46
>>621 ってことは、コンストラクタでメンバ関数のアドレスを引き渡すのも危ないってことですよね。
コンストラクタ内でそのメンバ関数のアドレスを使わなければ大丈夫。
624 :
618 :2008/04/19(土) 16:18:31
>>623 なるほど。理解しました。
どうもありがとうございました。
実体は生成される途中にある。 だから、this は存在する。 存在するが、その実体は完全に生成されていないので、 その実体を操作しようとすると色々な不具合が生じる。 1. メンバ変数が全て生成されている保証は無い。 → メンバ変数に触る関数を呼ぶとヤバい。 2. 仮想関数の呼び出しが正常に働かない。 → class B : public A { B() : c(this) { } void hoge(); C c; }; とした時、B のコンストラクタ内から仮想関数 hoge を呼ぶと どんな状況であろうが B::hoge が呼ばれるが、 C のコンストラクタ内から渡されたポインタを使って仮想関数 hoge を呼ぼうとすると どんな状況であろうが A::hoge が呼ばれる。 B の基本的な初期化が済んでないので、B::hoge を呼ぶ事は非常に危険ということでそうなるのだが、 もちろん A::hoge が呼ばれてしまう事も危険っちゃ危険だ。
626 :
618 :2008/04/19(土) 16:37:18
ん...また混乱..
>>1 . メンバ変数が全て生成されている保証は無い。
>> → メンバ変数に触る関数を呼ぶとヤバい。
これだと、例えば,
class AAA {
public:
// 危険?
AAA(){
this->value = 5;
};
// こちらにしなくてはならない?
AAA():value( 5 ){
};
void test(){
cout<<value<<endl;
};
private:
int value;
}
ということ?
ここで言っているのは、コンストラクタ以外のメンバ関数のことでしょ。 普通、メンバ関数は、コンストラクタによって適切に初期化済みであることを 前提にして書かれているから、 コンストラクタの途中で呼び出すのは、一般的には危険ということ。
vptrは初期化リストに先立って初期化されてるはずだから、 実装的には値が不定なだけだと思うけど、 未定義ではあると思うよ。
補足。this->nとかの値が不定って意味ね。
前に VC6 でやった時は仮想関数テーブルの初期化は最後だったけど、 どっちの仮想関数が呼ばれるかって仕様で決まってんのか?
え〜うそ〜!? 基底のコンストラクタから、 派生の仮想関数が呼ばれない、とかの話と勘違いしてない?
基底に this は流石に渡さんぜよ。
>>631 VC++だと__declspec(novtable)を付けたクラスでは
vtblの初期化が行われないなんて独自拡張がある。
(最派生クラスだけnovtable無しにして使う)
これ使っていないか?
novtableいいよねー コード縮むし
|┃三 |┃ |┃ ≡ _、_ ____.|ミ\___( <_,` ) |┃=___ \ |┃ ≡ )ATL 人 \ ガラッ
class Derived : Base {...} void f(){ Derived v; } this->vptr = &Base::vtbl → Base::メンバ初期化 → Base::ctor → this->vptr = &Derived::vtbl → Derived::メンバ初期化(定義順にctor) → Derived::ctor Derived::dtor → Derived::メンバ破棄(定義逆順にdtor) → this->vptr = &Base::vtbl → Base::dtor → Base::メンバ破棄(定義逆順にdtor) → this->vptr = 不定値 こういう流れになるはず。VC6も。
638 :
637 :2008/04/19(土) 21:28:41
表現がおかしかったので訂正。 × Base::メンバ初期化 ○ Base::定義順にメンバ初期化 × Derived::メンバ初期化(定義順にctor) ○ Derived::定義順にメンバ初期化 ctorは「メンバの暗黙の初期化・初期化リストによる初期化」を含まないコンストラクタの中身。 dtorは「メンバのデストラクタ呼び出し」を含まないデストラクタの中身。
VCの実装を見る限りcinやcoutはextern修飾されてるみたいですが、 宣言のみの必要な定義のいらないこれらの様なものを自分でも書くとき、 一般的にどのコンパイラでも単にexternを付けておけば良いんでしょうか?
externが、必要がでるまでどこかで定義された実体を探す事がないという保証があるかどうか?
日h(ry
template<class T> struct A { struct B {}; }; template<class T> void f( typename A<T>::B ) {} と定義して f( A<int>::B() ); とすると 'void f(A<T>::B)' : テンプレート 引数を 'T' に対して減少できませんでした というエラーが出るのですが、入れ子クラスではテンプレートの引数を推測でき ないのでしょうか?
f( A<int>::B() ); を f<int>( A<int>::B() ); と推測できないかってこと? それは無理がありすぎるな。
逆にboost::implicit_castがこれを使っていて、 推論を抑えるため、引数の型をtypename mpl::identity<T>::typeにしている。
BがAのテンプレートパラメータTの値をtypedefの形で保持してそれをf側で参照するようにしてやれば可能になりそうだけど そうするとfを関数オブジェクトにしないといけなくなってC++の暗黒面に突入する…と 本当にunk言語だな
何で std::auto_ptr<char> x( new int ); はコンパイルエラーにならないんですか?
おまえがどんなコンパイラと、どんなSTLの実装使っているのか非常に気になる。
コンパイラは VC8 SP1 で STL はコンパイラ付属です。
VC8って2005だっけ? 2008ではエラーになったぞ。
8は2005
VC++2005Expressではエラーになった
VC7.1 だとエラーになりました。 Microsoft Visual Studio 2005 Version 8.0.50727.762 (SP.050727-7600) だとなぜかエラーになりません。 もしかして C++ コンパイラはエラーを出す義務はないのかな?
多分それはない。 コンパイラのバグか、誰かがヘッダ書き換えちゃったとか。
デバッガで追いかけたら new int が一旦 std::auto_ptr_ref<char> に 変換されてから std::auto_ptr<char> に変換されていました。 std::auto_ptr_ref<T> は void* 型でポインタを記憶しているので int 型は消えていました。 memory ヘッダーを確かめると確かにエラーが出ないはずです。 この動作は std::auto_ptr の仕様でしょうか?
いまだに信じられんな。もうすでにVC8なんて使っていないんだが、
それほど悪いコンパイラとSTLじゃなかったはずだが。
とりあえず
>>654 の話から想像すると、
rvalueとlvalueの境を越えるための、あまり汎用的に使い道のない、
汚いトリックを使ってauto_ptrを実装しているが(オーバーロードとtemplate argument deductionのわずかな違いを利用するやつ)
普通に使う際にも、そのトリックが働いてしまうって事かな。
STLの実装の問題っぽいかなぁ。
ふつうauto_ptr_refのメンバをvoid *にしなければならない理由はないよな。
>>655 あ、
>>656 に加えて、auto_ptr_refのコンストラクタがexplicitじゃないのか。
だめじゃん、P.J. Plaugerさん。
失礼 リソースの 切り離し / 復元 を実行するメソッドの命名に困っているのですが この意味に近くて使いやすい単語のペアはありませんかね? 機能的に必ず対になるものです。 候補としては [Detach / Restore] Detach の対義語は Attach だしな [Detach / Attach] Attach は「復元」では無い気がする [Destruction / Resotre] Destが長い [Destroy / Restore] Destory は Create のペアとして使ってきたので控えたい ですが、どうも腑に落ちません。
日本語の「切り離し」と「復元」はそもそも対義語じゃないよね・・・ 切り離しとその反対なら、Detach / Attach だろうし、 復元とその反対なら、Save / Restore だろう。 Destruction なんて破壊しちゃうわけでさ、英語以前に日本語の 「切り離し」「復元」ってのがそもそも違うんじゃないか?
660 :
658 :2008/04/24(木) 20:08:51
>> 659 > 英語以前に日本語の「切り離し」「復元」ってのがそもそも違うんじゃないか? うーむ・・仰るとおりですね 切り離しを実行すると 消失 という状態になる処理だったので それを元に戻す意味で 復元 と考えていたのですが もう少し考え直してみます。 ありがとうございました
漏れはホンちゃんの処理の準備のためのナニにはPrepareXXXを結構使うな。 オフスクリーンビットマップやら何やらの準備とか。
release / acquire
>>660 Disconnect / ReConnect とか、Detach / ReAttach とかは?
664 :
658 :2008/04/24(木) 22:43:04
>>661 Prepare
今回は使いそうに無いけど、ひとつ賢くなりました
>>662 そういえば DirectInput に Acquire / UnAcquire (だったかな)ってのがありますね
これ良いかも
>>663 Disconnect / ReConnect
接続とはちょっと違うんですわ
ありがとうございました
スマートに命名出来るように、もうすこし設計から見直すことにします
template <template<class> class T> このようなテンプレートテンプレートパラメータが なぜこんな書き方ができるのか今一理解できません。 誰か上手いこと説明してください
なぜ出来るのかって、そりゃ出来るように言語仕様を改定して コンパイラが対応したからだろ・・・
class X を渡せる奴は template <class X> と書くんだから template <class A> class T を渡せる奴は template <template <class A> class T> と書けるようにするのが自然だろう。 むしろ他にどんな書き方があるのかと問いたい。
>>667 あぁ納得。
<template <class A>
最初の例だとAの部分が無かったので混乱してました
現行規格でも次期規格の最新のドラフトでも throw() ついてるから。
だから聞いてるんじゃね
throw() は例外を投げない事を保証するが、 unexpected() が呼ばれて落ちる事もあるので 「throw() がついてないからどんな例外が呼ばれるか分からないから 落ちる可能性があるかもしれないのか不安だよ!」 ってのは意外とナンセンスな悩み。
>>672 ナンセンスな私的だな。例外安全性について勉強し直せば。
例外指定にない例外を投げたらunexpected()呼ばれるんじゃなかったっけ つまり例外指定はあんま意味ナス
throw()は意味あるよ。関数の実装者がユーザに対して例外を投げない事を保証するものだから。 ユーザはthrow()を見て、例外不送出であることを期待してコードを書く事ができる。 unexpected()が呼ばれる事で、その関数の例外指定に問題があるか、実装に問題がある事をユーザ/実装者が知る事ができる。
VCは例外指定無視する(そして"実装されてないお"と警告をだす)のでVC付属のライブラリからも外しちゃったんじゃない?
throwをつけると、おき得る例外を特定できるから、それを期待してプログラムを書ける。 なのにそれ以外の例外が投げられるという例外中の例外がunexpectedなのだな。例外にも階層があるんだね。
>>676 空のthrow()だけ対応していなかったっけ?
>>678 なんかそんな気もする
帰ったら確認してみるよ
>>678 そだよ。
書いても警告が出るだけだから。
vc9で確認してみた Debugビルドだと、throw()指定がついた関数内に直接throw文を書くとコンパイル時に警告C4297が出る。 実行時はthrow()指定無視 Releaseビルドだと、throw()指定がついた関数内に直接throw文を書くとコンパイル時に警告C4297が出る。 実行時はthrow文のところでterminateによりabort のようだ
VC9は何かバグバグだな 早くSP1出して欲しい でも年末とか言ってたような希ガス・・・・orz
>>669 例外指定があろうとなかろうと、
投げてくる(こない)例外の種類は、規格通りだから安心して使っていいよ。
void f( T a ) {} f の呼び出しで a を生成するときに起きる例外は f の中で発生する 例外ですか,それとも外で発生する例外ですか?
外
>>684 f()に入れる前に出ちゃってるんだから大丈夫。
もう、出しちゃったの?
Winsock2.0で非同期通信について教えてくれ connectメソッド使ってサーバに接続要求して サーバ側でACCEPTメッセージちゃんと受け取って 接続できてるのに戻り値が0にならないのは何で?
とりあえずWSAGetLastErrorでエラー内容調べてみたら?
>>689 やってんだけどわかんないんだ
非同期通信の場合WSAEWOULDBLOCKが返されるのは正常
という記事は見つけたんだけど、鯖立ててない状態で接続しても
WSAEWOULDBLOCKしか返らないからエラー処理出来なくて困ったちゃん
C++のnamespaceとオブジェクトに関連した質問させて下さい。 namespace Aにあるクラスまたは構造体のオブジェクトを、 namespace Bのクラスに引数として渡したいのですが、どのように 記述すればいいのでしょう?出来ればnamespace AとBは別々に、 それがダメならnamespace Aの中にBがいるように出来ればと 思っています。 C++を触りはじめたばかりでわかっていないことが多いのですが、 よろしくお願いします。
namespace AのclassXなら「A::X」
std::vector::size_type 型のオブジェクトは std::size_t 型の オブジェクトに変換できるでしょうか?
>>694 符号なし整数で、difference_typeの全ての非負数を表す事ができる。
としか書かれてないから、実装依存じゃないかな。
教えてください。 Visual Studio 2005をつかっています。 クラスのコンストラクタ内で動的に2次元配列を生成し、 ファイルから値を入力したいのですが、 デバッグ(ローカル,this,vec_x内)で確認すると、2次元配列にはなっているのですが、 行数、列数で共に1となってしまっています。 int **vec_x; int **vec_y; と宣言し、コンストラクタ内で、 vec_x = new int * [ size_y ]; vec_y = new int * [ size_y ]; for(i = 0; i<size_y; i++){ vec_x[i] = new int[size_x]; vec_y[i] = new int[size_x]; } size_y,size_xは初回のnewの次点ですでに、 300,200となっていることは確認済みです。
>>696 何を根拠に行数、列数が1と判断したのか詳しく。
つーか、vector<vector< int> >使ったら?
>>696 デバッガでは配列の要素数は型情報として存在しない限り
表示されないというか new [hoge] で取ったサイズは表示されないというか、
要するにただのポインタなので要素は1つしか表示されないというか、
まぁそんな感じ。
699 :
696 :2008/04/28(月) 16:51:46
>>697 デバッグで、ローカル変数タブからです。
this以下、vec_x(int **)を見ると、
(int *)に対応するところが1段しかありませんでした。
さらに、その下(?)の階層にも要素はひとつしかありませんでした。
>>698 その要素に値を入力したとき、
うまく領域が確保できていればどう表示されるんでしょうか。
>>699 詳細は>698の通り。そのデバッガは(newで確保した)可変長配列に対応していないのだろう。
確保できていたかどうかを知る手段はない。
確保に失敗したかどうかは例外が送出されるので受け取ればいい。
つーか、>697の最終行。
701 :
696 :2008/04/28(月) 17:13:14
むしろ、その後の値の入力に問題があるのかもしれません。
ifstream ifs("FILE_NAME");
ifs >> size_x >> size_y;
for( i = 0;i<size_y;i++){
for( j = 0;j < size_x; j++){
ifs >> vec_x[i][j] >> vec_y[i][j];
}
}
としています。
入力ファイルの中身は、
整数(半角スペース)整数
整数(半角スペース)整数
...
となっており、最初にsize_x,size_yを入力しています。
size_x,size_y,vec_x[0][0]は正しく入力されたのですが、
vex_y[0][0]には正しい値は入っていません。
その後のvex_x,vec_yの各要素の値に関しても同様に正しい値は入力されませんでした。
>>697 STLはややこしくて全く手をつけていません。
お恥ずかしい限りですが…。
>>701 g++ で一応試したけど、配列は
>>696 で問題無いよ。
俺も STL 使った方がいろいろと簡単だとは思うけど。
STLに限らず、まとまった規模の情報は何でもそうだけど、遠目に見ているうちは 頻繁に使うものと滅多に使わないものが「同じ大きさ」に見えるんで、 無駄に全容を眺めてしまって、「難しそうだなぁ」という気持ちばかり膨らんでいく。 実際には「STLを使う」ってのは、その殆どがつまり「コンテナを使う」ってことで、 これ自体はめちゃくちゃ簡単な話だよ。
704 :
696 :2008/04/28(月) 18:00:02
>>704 それで使い方はいいよ。
違うよ。2個目の引数は vect1 の各要素を初期化というか instantiate してる。
constructor は 2 つ引数あるときは個数と各要素。
>>705 下の文に引用が無いから
> それで使い方はいいよ。
> 違うよ。
が繋がった感じで、なんかワロタ
クラスAからpublic派生したクラスBで、クラスA分のメンバ関数をprivateにしたいんですが Virtual付いてると宣言だけじゃ駄目なんでしょうか? 環境はBCB5+XPです class a { public: void Test1() {}; virtual void Test2() {}; }; class b : public a { private: void Test1(); //OK virtual void Test2(); //リンカエラーが出る };
virtualは関数の実体を定義しないとエラーになるよ。
それが許されたとして、aの中でよんでいるTest2はどうなるのか興味浦々
う〜んそうだったんだ。 a.Test2()で実体があるから、問題ないんじゃないかと思ってたけど 違うのか。 すごく勉強になったよ。ありがとう〜
class b : public a { private: using a::Test1; using a::Test2; }; やりたいのはこういうことか?
>>711 この書き方は知らなかった。
usingについて調べてみます。
じぇねれーてぃぶこーどって本 買ったけどC++のソース部分読めない たじゅけて
出版社に送って新しいのと取り替えてもらえ
無限ループになる悪寒
>>714 当社では、「落丁・乱丁」の場合のみお取替えをさせていただいております。
大変申し訳ありませんが、「ソースコードが理解できない」お客様につきましては、
対応いたしかねますので、ご了承いただけますよう重ねてお願いいたします。
>>713 何がそんなに難しいの? template とかの勉強が必要なのかな?
じぇねれーてぃぶこーどなんて本あったっけ?
日本語ではなかった気がする
hoge
722 :
デフォルトの名無しさん :2008/05/06(火) 11:39:15
int main () { static int i (0); struct Local { static void increment () { ++ i; } }; Local::increment (); } 関数内のクラスのstaticメンバ関数(Local::increment)から 関数内の変数(i)を触れるのは規格に合ってる? g++.real (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) では触れるのだけど.
スタティックなメンバ関数からスタティックなメンバ変数が見えるのはいいんでないかい? 別に矛盾はないと思うし。 スタティックなメンバ変数ってのは、スコープ限定のグローバル変数みたいなもんだしね。
>>723 そういう事なんだろうね。俺も
>>722 さんの code 見てちょっと
えっ?て思ったけど、気分悪いがはっきりと間違っているとも言えない。
実際 compile してみると走るし(g++ 4.1.1)。どちらの static でも
外せば compile しない。
725 :
722 :2008/05/06(火) 15:42:33
>>723 ,724
規格に合っているみたい.
9.8.1に
722ほぼそのまんまの例が載ってました.
int* array[10]; ってnewでやる場合どう書けばいいですか?
array[0] = new int[931];
>>726 もっと分かるように質問しろお( ^ω^)
int** array = new int*[10];でしょjk
C++のソースコードをアセンブラのコードに変換する方法があるって聞いたんですが どうやればいいか教えてください コンパイラはVCです
コンパイラオプションで「アセンブリコードを出力する」に設定する
730です ありがとうございます
void F( vecotr<int> &vec ) { struct T { void operator()( int i ){ printf( "%d\n", i ); } }; for_each( vec.begin(), vec.end(), T() ); } こういう奴で、struct TをFのスコープ外にすると通るんだけど、 スコープ内だと通らない。 なんで? なんで?って考えちゃダメ?
>>733 関数ないクラス、構造体はtemplateクラスやtemplate関数にtemplate引数として渡せないと仕様で決まっている。
誤字修正 x 関数ないクラス o C++仕様もまともに知らない奴は死ね
x 関数ない o 関数内 こういうことだろ
x こういうことだろ o べ、別にあんたの為に修正してやってるんじゃないんだからねっ!
>733 C++STDの14.3.1.2で不可になってますな。 コンパイル時に特定する必要があるので、外部リンケージの無い要素を指定できないんですな。 そういう意味で文字列リテラルも不可。 #文字列リテラルを実引数にできると色々と面白いんだけど、しようがないか……
外部リンケージ?
ケータイ小説・千の風になっての評価 評価者:ミカ 評価:★★★★★ ミカと同じ名前で同じ歳の子がこんなひどい人生を送るなんて!! 信じられない!! 一晩中泣きました!! 評価者:サナエ 評価:★★★★☆ これがあたしたちのリアル。 評価者:ち†ょ⊃ 評価:★★★★★ 寝ゐ前|ニ言売ゐ女台め†ニяа止маω†ょ<τ 冫欠σ日シ立L≠†ょカヽ〃яа学木交|ニ彳テL≠маU†ニ
ちなつ 寝る前に読み始めたら止まんなくて 次の日泣きながら学校に行きました 同じ文字を複数の文字にあてたり、いきなりローマ字とか出てくるとワケワカメになるね。
ドストエフスキー小説・罪と罰の評価 評価者:ラスコーリニコフ 評価:★★★★★ 僕と同じ名前で同じ歳の人がこんなひどい人生を送るなんて!! 信じられない!! 一晩中泣きました!! 評価者:ドストエフスキー 評価:★★★★☆ これがあたしたちのリアル。 評価者:ポルフィーリィ 評価:★★★★★ 予審前に読み始めたら止まんなくて 次の日泣きながら仕事に行きました
おい 自演してる奴がいるぞ しかも評価は控えめw
1 2 3 4 . __ __ _ ,i,_,i_ ,-,_ ,-i,_,l 、 :.. :. ≡=-i'__l, | `i /'-' `i //l l iコ==ラ`'i ti | lヽi li, → | lヽl li → l i,,l l | → ./ /l/ | l-'l |,l | | // l `"|iコ='' / / . 'Fヲ|,H E三l_l_A | .i .| / / ,i_| .| | | || | i' /l .l, -'‐' | || |_ l l .ヽ,ヽ, ‐' ' `‐' -'-' -'-' 脱ぐ たたむ プログラムを src と dest を つくる まちがえる。
>>742 >評価者:ポルフィーリィ 評価:★★★★★
>予審前に読み始めたら止まんなくて
>次の日泣きながら仕事に行きました
あんたが言うせりふやない。
747 :
デフォルトの名無しさん :2008/05/10(土) 15:18:13
重複しない複数の座標値、x,y,zという3つのキーを用いて、 そのキー(座標)の要素に値を代入、変更する処理を行おうと思っています。 現在、 class XYZ { int x; int y; int z; int value; }; としてXYZの配列を計算したい領域分だけ確保しているのですが 任意のx,y,zで値の変更があった場合,そのキーの要素を検索して参照、代入する方法として 何かよい方法はありませんでしょうか? よろしくお願いいたします。
管理が冗長すぎるだろ
std::map<int, std::map<int, std::map<int, int> > > m; m[x][y][z] = value;
m[x][y][z]って・・・
志村XYZのDVDって出てたっけ?
>>747 言いたいことがよくわからない。
キーが与えられたら要素を返す method と代入する method (というか
メンバ関数)を作るってことじゃないの?変更がどうあるのかもよくわからん。
XYZにoperator< を定義してsetに突っ込む
>>747 3次元座標値ってどんな領域なのよ?
まず問題の概要を説明しやがれ
このスカポンタン
これでいいだろ #include<map> class XYZ { int x, y, z; public: XYZ(int x, int y, int z) : x(x), y(y), z(z) {} bool operator<(const XYZ& rhs) const { return x < rhs.x || (x == rhs.x && (y < rhs.y || (y == rhs.y && z < rhs.z))); } }; int main() { std::map<XYZ,int> m; m[XYZ(0,1,2)] = 100; }
#include <new> としているコードを見かけますが、 わざわざ<new>をインクルードするのなぜなのでしょうか? インクルードしなくてもnewは普通に使えますよね?
いらないと思うんだった、コメントアウトして再コンパイルしてみればいいんじゃね? 単に習慣でインクルードしてるだけかもしれないし。
placement new, std::nothrow, std::bad_alloc を利用する際にインクルードするヘッダファイルであって、 普通の new を使うためにインクルードするヘッダファイルではない。
>>757 precement newやnew演算子のオーバーロードをするときに使う。
オーバーロードする際に必要だっけ?
そんな事はない
だよねー
かわいい女の子が寝る前に 1分間枕元に立ってくれるための おまじないだと、先輩から聞いたことがる。
映画版呪怨ですね。わかります。
struct xstring_traits{ bool is_w() const {...} ... }; struct vstring_ref { // デフォルトコピーコンストラクタ使用 const xstring_traits* tr_; const char* begin_; const char* end_; const wchar_t* wbegin(){return tr_->is_w() ? reinterpret_cast<const wchar_t*>(begin_) : NULL;} ... }; struct vstring_buffer { const xstring_traits* tr_; char* begin_; char* end_; ... }; struct vstring {...}; // コピーでメモリ再確保
767 :
766 :2008/05/12(月) 00:40:35
(続き) やっぱ引数がconst std::stringだと std::string以外から受け取る場合のコストが気持ち悪いし、 const char* でことあるごとにstrlenとかするのも無駄だし、 WindowsだとTCHARとかの場合もあるけど、 WinAPIに関係無い部分にまで<tchar.h>入れるの嫌だし。 で、ただでさえ多い文字列クラスをさらに増やすのかと 葛藤しつつも自作文字列クラスを・・・。 皆はやっぱり普通にstd::string? Windowsの場合は、 typedef std::basic_string<TCHAR>する人もいるよね。
768 :
766 :2008/05/12(月) 00:41:33
×引数がconst std::string ○引数がconst std::string&
俺は、普段はconst std::string&で済ます。 std::basic_string<TCHAR>のtypedefもWindowsプログラムならよく使う。 767も言うコストが気になるならRangeを引数に取るテンプレートにする。
スレチだけど俺は TCHAR でちゃんと動くコード(mbcsをちゃんと処理するコード)を 書く気はさらさらないので、欺瞞的なTCHARの使用はなるべく避けてWCHARにしてる。
俺も全部 TCHAR で書いてるけど、string::find とか平気で使ってるわ。 mbcs じゃほとんど動かんコードになってる。
>>767 文字数が必要ならこうする手も。
void hoge(const char* str, size_t len) { }
inline void hoge(const std::string& str) { hoge(str.c_str(), str.length()); }
なんで、private継承、protected継承すると、アップキャストができなくなるのだ?
外からprivateなメンバにアクセスできないのと同じ 外からprivateな基本クラスにはアクセスできない
>>773 外からできなくなるだけで、中からならアップキャストできるよ。
private継承するboost::operatorsがなんで動作するのかも良くわかんないな。
分かんない事ばかりなのに使わなければならないC++って、怖くね?
>>776 friend関数はクラスのメンバではないから・・・かな?
class A {
private:
friend void foo() { ... } // メンバのように見えるけど実はグローバル関数なのでアクセス制御は効かない
};
int main() {
foo();
}
C++以外の言語も使いますが分からないことだらけです。
何が分からないか判っていれば解ったも同然だ
781 :
デフォルトの名無しさん :2008/05/13(火) 19:54:24
friend関数、VC2005からtemplate<class T>を頭につけないと コンパイルが通らなくなったんですね。C++0xはまだなのに こういう仕様変更はひそかにやってるんですか? それとも、もともと規格書にはこう決められていてやっと Vc++2005で対応できた、ということですか?
>>777 わかんない部分は無理して使う必要はないし。
でも、わかった後それを使うと今までだらだら長く書いていたコードがすっかりコンパクトにまとまってショックを受けることが多々ある。
>>781 それは後者
でも前者みたいなひそかな変更もVC++はよくやる。
いや、きちんと文書化されているけどね。
例えばtype traits支援とかC99の%a書式とか。
確かにめんどくさいし手間が掛かる…
C++ Programming Languageを端から端まで二度読める知能があれば右辺値参照ごときにどうして瞼が落ちるのか。
落ち着かない仕様 時間の掛かる修正 度重なる保守
C++は仕事に向かない言語とういのには同意だな
C++ Programming Languageを二度読むのに必要なのは知能ではなくて忍耐力だからな
性能に取り憑かれているのは自分でも気づいているがどうしてもやめられない。
Java も使うけど、C++ の方が楽に感じる事多いな。 気を付けないと保守が大変というのはわかる。 ただ、どの言語でも保守の問題はあるし、気を付ければ そんなに問題ないと思ってるけど。まぁ、5年後になんて 言っているかはわからんが。
C++の全機能を使わなければならない、という規約でもあったのだろうか? 演算子オーバロードは危険だと思ったなら、単にその機能を使わなければよい。 参照は不要でポインタがあれば十分だと思ったなら、単にその機能を使わなければよい。 添え字が範囲の中にあるかテストしてほしいと思ったなら、at()メンバ関数を使えばよい。 なぜ、C++の全機能 vs Cの比較なんだろう? C+α(Better C) vs Cの比較をしないのはなぜだ? 要するに、マヌケだってことだ。
>>784 のリンク先
C++に過剰に複雑なところがあるのは同意なので、
その人(翻訳者でなく)がC++嫌ですって言うこと自体に批判は特に無いけど、
ちょっとツッコミ書くてst。
>C の方を使いたくなる
別に複雑な機能を使わなくても、
・#defineマクロ(MAXなど)の代わり程度のtemplate
・fopen,fcloseみたいなのをRAIIに扱うための極薄ラッパー
などの簡単で便利なものだけ「better C+おまけ」程度に使えば良いと思う。
巧みで知識もあると言う割には、要領が悪い気がしないでもない。
>Java や Groovy に
そこでGroovyは無いと思う・・・
俺もjava好きだから良いんだけど、
もうちょっと他の言語も挙げれば良いのに・・・
>そこでGroovyは無いと思う・・・ ググったら実質両方Javaでワロタw
>>792 > C+α(Better C) vs Cの比較をしないのはなぜだ?
自分一人で遊んでいるときしか、そういう使い方がうまくいかないからでは。
なぜ今更そのネタを
>>792 > C++の全機能を使わなければならない、という規約でもあったのだろうか?
あるとしたら逆だろう。○○しか使ってはいけない、という規約が無くてカオス化する。
あるいは、そういう規約がちゃんと機能して、自分の仕事がうまくいっているとしても、
「ここまでの規約が無ければ収拾つかなくなるC++って・・・」という虚しさは感じることになる。
「C++に文句を言う奴は、C++を使い切れないマヌケだけ」
というのは、C++信者の反撃としては割とお約束だし、部分的には当たっている。
実際、「一人でちょっとしたものを作ることさえできない」人間の八つ当たりも結構見られるし。
ただ、C++の難点というのは、主に「個人の能力ではどうにもならないところ」に表れるものであって、
この話を個人の能力に全部収めて着地させようというのは、わかっててやってるなら
いかにも姑息な「問題のすり替え」ではある。
> 個人の能力ではどうにもならないところ ってどこだろう
他人の脳味噌は自分の脳味噌ではない、という事実とか、 そういう風にして複数の脳味噌によって構築された「すんげえ規模」とか。
名前マングリングとかABIとかじゃね
C++最高!とまでは言わないが、ハードと離れた言語は使う気しないな
>>799 それはC++に限った話じゃないな
CでもJavaでもPHPでもよくある話だ
>>800 ABIが規定されていてうまく機能している言語ってあります?
ちなみに、自分はC++信者なわけではない
素直な感想と疑問
>>797 どの言語でも仕事で coding する時は文法的に正しければなんでも良い
なんてことは無いはずだが。規約を全く無くせば収拾つかなくなると思うが。
規約を決めるのを C++ に限ったことではない。
元の記事はむしろ binary の compatibility を問題にしてるんじゃないかな。
>>802-803 「有るか無いかでいったら、どの言語にだってあるぞ」
というのは確かにその通りだけど、この場合はC++の「度合いのひどさ」を問題にしているわけで、
ゼロじゃないからどの言語もみんな仲間! ってのは、話の持って行き方としてちょっと違うと思う。
>>804 でもJavaぐらいだと
>>799 の問題は似たようなものな気がするけど
だんだん複雑になってきてるし
ある程度表現力が高い言語になると普遍的な問題じゃないかな
C++だとまともに書けない人でもJavaなら書けるのだろうか
そんな人がPythonならまともに書けるのか?
規模の問題はちょっと違うだろうね。 名前マングリングに関しては確かにC++のは委員会とかの人も 普通に「どうにかしたい」って思ってそうだけど、 実質、ABIがさえ合えば問題無し、って程簡単じゃないから 再コンパイルした方が良い。 UNIX、Linux系ではオプションの変更程度で再makeすることも多いし。 それに完全にバイナリで使うなら.soとか.dllで考え方が良い。
例外とか this ポインタの実装手段の違いとかも問題になるんじゃね。
>>797 で言っている問題で、何でも使うか使わないかは、
compile し直そうが残る問題が多いけど。特に保守性考えると。
件の ABI の問題は compile し直せばいい問題じゃないの?
(だから問題になりえないと言っているわけではないが)
ちょっと違うことを問題にしていて議論が混ざってる気がする。
質問があります 代入演算子をprotectedないしprivateにしたいんですが、 実装はデフォルトで生成されるものそのままでいいんです class Hoge { // さまざまなメンバ変数(代入演算子があったりなかったりする) Hage hage; Fuga fuga; int hensuu; protected: Hoge& operator=(const Hoge&); }; ってやったらリンクエラーになるんですがどうすればいいでしょう イチイチ中身書くのも面倒で・・・
イチイチ中身書くしかない
C++0x では default キーワードでデフォルト実装を作ってくれるそうです。
handle-bodyイディオムで書いて、handleの代入演算子をprotectedなりにすればどう?
バイナリとしての0x00をchar配列に格納したいんですが、終端文字として認識されてしまいます。 こういう時ってどうすればいいのでしょうか?? ご教示いただけると幸いです。
もしかしてstrcpyとか使ってるのか?
815 :
デフォルトの名無しさん :2008/05/17(土) 01:21:39
レスどもです。 いえ、const char [] 型に0x00を含む文字列を格納して、cout とかで出力しようとすると0x00以降が出力されないんです。
考えるだけでも恐ろしい
817 :
デフォルトの名無しさん :2008/05/17(土) 01:22:59
それは当たり前 仕様 0は文末というのが原則です。
818 :
デフォルトの名無しさん :2008/05/17(土) 01:24:21
出力させたいんだったら、string使えば出来るはず。 こっちはサイズまではちゃんと出力したと思う。 たとえばstr.resize(10000,'\0'); cout<<str;とする。
とすると、バイナリとしての0x00を途中に含むchar文字列を作りたいんですが、無理なんでしょうか??
820 :
デフォルトの名無しさん :2008/05/17(土) 01:25:58
0を含むchar配列はできるよ でもstrlenとかは間違える 自分で長さを管理すればよい。
821 :
デフォルトの名無しさん :2008/05/17(土) 01:27:56
たとええばchar配列で0を含まないならstrcpy、strcmpなどを使い、 0を含むなら長さを自分で指定するmemcpyやmemcmpを使う。
いや作れるよ char配列の内容がNTCSであることを仮定している関数・APIに NTCSでないchar配列を突っ込んでいることが間違いなだけ
なるほど! 0x00を入れると格納はされているけど出力できていなかったということですね。 長さを指定したら出力できました。 レス下さった方々ありがとうございましたm(_ _)m
824 :
デフォルトの名無しさん :2008/05/18(日) 02:40:02
質問です。 目標は,動画編集アプリケーションの作成です。 C++(C++/CLI win32api), VC++, C#, Java の中なら,どれを選択すべきでしょうか? (ちなみに,上記4つと、C,PHP, JSP/Servletの基礎は習得致しました。)
C# か C++ でいいんじゃね。
不特定多数のユーザーを想定すると .NET をインストールさせるのは気が引けるよね
いつまでXP使ってるんだよ。
企業では2000が余裕で現役ですよ
830 :
824 :2008/05/18(日) 03:03:26
求人情報で、よく"C++経験者歓迎"と書かれています。 この"C++"とは、VC or C++Builder どっちを指しているのでしょうか? C++で動画編集アプリケーション作成する場合、参考になる本はありますか? ご教授お願いします
どっちでもいいんじゃね 経験者歓迎っつうのは仕事で使った事あるかという事だが
ターゲット環境は Windows そうだから DirectDraw について勉強しよう
833 :
824 :2008/05/18(日) 04:07:35
>>825 >>826 >>827 >>831 >>832 さん。ありがとうございました。
まず、DirectXの勉強をいたします。。
もし、オススメの本をご存知なら、教えてください。
お願いいたします。
現段階で私が選らんだ本は、
マスタリングDirectXプログラミング
DirectX ゲームグラフィックス プログラミング Ver. 2.1 Vista
です。
DirectX関連のスレで聞いた方がよくない? 動画編集といいつつ、実はニコ動投稿用を想定してるとかなら、C#で十分な気も。 プログラミングの勉強という意味ならC++でいいと思うけど。
836 :
デフォルトの名無しさん :2008/05/18(日) 13:22:19
=演算子をオーバーロードして、その中でデフォルトの=(オーバーロードしていないときの=)を使うことはできますか? cClass &operator = (const cClass &a) { ここでデフォルトの「=」を使いたい! ・ ・ ・ }
自分で定義しちゃうと デフォルトの = が定義されないから 無理やね。残念ながら。
839 :
824 :2008/05/18(日) 14:24:49
>>834 レス、ありがとうございます。
今回は,ニコ動投稿を考えていません。
(ただ,面白そうなので,そのうちアプリケーションに追加したいと思ってます)
主に,プログラミングの勉強です。
>>835 !!!
ありがとうございます。
現時点では,洋書はすらすらと読めません。
そのため,和書のDirectX本でDirectXの基礎を勉強する。
それから,英語・DirectShowの勉強を始めます。
皆さん,本当にありがとうございました。
DirectShow はネット上の情報が少ないから頑張れ。
DirectShowと戦うスレってPart 3の後立ってないんだな。 Part4立てちゃってもいいかも。
>>835 おお、そうだった
自分も苦労したのに、もう忘れてる
DirectShowはMSDNに超詳しく載ってるだろ 要はCOMなので分かってればそうそう難しくもない
COMこわいよ あー頭が割れるくぉおおぉぉx COMがぁCOMがぁ襲ってくるよぉ ハァハァハァ
846 :
デフォルトの名無しさん :2008/05/19(月) 00:13:38
MinGWを使っているのですが、int型の10をstring型オブジェクトに変換すると、データがおかしくなりませんか?? string s; s = 10; ofstream fout("test.txt"); fout << s; このプログラムで出力したtest.txtをバイナリエディタで見てみると、 0x0D 0x0A となっています。0x0Dってのはなんなのでしょう。 11の時はちゃんと0x0Bだけになっているし、20の時はちゃんと0x14だけになっています。 なぜか10の時だけ0x0Dが付加されてます。
変・・・換・・・?
ファイルをテキストモードで開いてるときは、\n(0A) → \r\n(0D 0A) に変換される バイナリモードで開けばおk
> s = 10; まずここが間違い。 stringstreamを使うこと。
850 :
846 :2008/05/19(月) 00:40:40
なるほどっ。。テキストモードで開いているせいだったんですね。。 ありがとうございましたm(_ _)m すいませんついでにもう1つ教えていただきたいのですが、 string s; s = 20; ofstream("test.txt"); fout << s; のような感じにすると、バイナリの0x14がちゃんと出力されるので string型オブジェクト = int型の値 の代入で、うまいぐあいにstring型に変換してくれるのだと思っていたのですが、 ふと2バイト以上必要な数値はどうなるのだろうと思って s = 512; fout << s; のようにしてみると、0x00が出力されてしまいました。 2バイト以上必要な数値でもうまくstring型のオブジェクトに格納するにはどのようにすればよいのでしょうか?? アドバイスいただけると幸いです。
851 :
846 :2008/05/19(月) 00:44:27
>>849 すいませんリロードしないで書き込んでました。
stringstream ss;
ss << (char)20;
のような感じでうまくいきました!ありがとうございましたm(_ _)m
stringstreamか,面倒ならboost::lexical_castを
853 :
846 :2008/05/19(月) 00:59:41
すいません、解決した・・と思ったのですが、
stringstream ss;
ss << 512;
とすると、stringstreamでも0x00が出力されてしまっていました。
このやり方では2バイト必要な文字の場合は最後の1バイトしか出力されないようなのですが、
stringオブジェクトに 例えば 10進数の513をバイナリの0x01 0x01 と格納したいような時はどうすればよいでしょうか・・
>>852 ありがとうございます。調べてみます。
854 :
846 :2008/05/19(月) 01:01:09
×2バイト必要な文字 ○2バイト必要な数字 ですね。。度々すいません。
> バイナリの0x14がちゃんと出力されるので それはstring型に変換しているとは言わないと思うんだが・・・。 バイト列を出力したいのか、文字列を出力したいのははっきりさせた方がいい。 文字列なら、例えば10進数で"20" "512"と出力されるだろう。
バイト列の出力ならchar*にして、stream.write()で。
あと、intとかをバイナリで書き出すなら ネットワークエンディアン(ビッグエンディアン)とかで出した方が良いと思う。
エンディアンを問わないなら、 int i = 513; ofstream fout("result.bin", ios::binary); fout.write((char*)&i, sizeof(i)); たぶんこんな感じ(テストしてないから間違ってるかも、あと環境依存がある)。
string s = 20 っていう初期化はコンパイルエラーになるけど、宣言した後の s = 20 っていう代入はエラーにならないんだな。この代入演算子は危ないだけのような 気がする。 char 1文字にしたけりゃ assign() 使えばいいし。
860 :
デフォルトの名無しさん :2008/05/20(火) 10:14:18
>>859 それって、stringクラスにint型からの型変換は定義されてないけど、
int型の代入演算子は定義されてる、ってこと?
>>860 char 型を受け取る代入演算子に int が食われてる。
>>859 g++ -Wall してみたけど、そうだね。
string s(20);
string s=20;
はだめで
string s; s=20; は warning 無しで OKってのは紛らわしい。
ついでに入ってるは DC4 とかだし。
これだから型付け緩いクソ言語は
>>863 C++ は自分を律せない人には使えない言語。
boost無しでは使いたくない事だけは確か
866 :
デフォルトの名無しさん :2008/05/20(火) 12:49:46
結局、ヘタしたらソースまで読んで、 細かいクラスの実装まで理解しないとプログラムできないのか・・・ オブジェクト指向って、そう言うことしなくても プログラムできるのがウリじゃなかった?
>>866 > オブジェクト指向って、そう言うことしなくても
> プログラムできるのがウリじゃなかった?
ちゃんとドキュメントがあれば問題はない。
Visual C++ では string オブジェクトに int を代入しようとするとエラーをはいたように思った。 あと、 stringstream はやめにしてこれからは sstream を使って頂戴って話になってなかったっけ?
ドキュメントがないとかオスになるのはどの言語でも一緒だしね。
>>866 何が言いたいんだかよくわからん。重箱の隅をつついたような
あいまいなコーディングをせず、安全第一でしなきゃいかんでしょ。
> 結局、ヘタしたらソースまで読んで、
> 細かいクラスの実装まで理解しないとプログラムできないのか・・・
どんな言語でも「ヘタしたらソースまで読んで…」というのは
当てはまると思うけどね。「ヘタしたら」なんだから。
どんなに頑張っても絶対にヘタをすることのできない 夢の言語と比較しての批判でしょう、たぶん。
>>865 仕事で書くソースにboostを使いたくない事だけは確か。
少なくとも俺はね・・・。
>>866 そういうウリは無いよ。
>>868 strstreamは使うな、の間違いじゃね?
sstreamはstringstream使うときにincludeするファイル名だよ。
boost無しでは使いたくないっていうのは 10年以上前から欠陥品って言われてるような標準のfunctionalとかstream系のような 欠陥品をそのまま使うなんてありえない、boostで提供される改良版使いたいっていう主張ね boostって標準ライブラリの欠点を補うようなものも多いし そういうのなら仕事でもガンガン使えると思うんだけどどうか
もう二度とboostのコードレビューはしたくありません。
875 :
デフォルトの名無しさん :2008/05/20(火) 22:31:19
C++って正直覚えることが多すぎてちょっと疲れたよ 他の言語で書いて速さが必要な箇所だけC++で書けばそれでいいんじゃなかろうか
それでいいんじゃないすか Cと違って他言語から呼び出すのは難しいけど Win限定ならC#でGUI書いてキツイ所はC++/CLIとかできるし
>>876 C++ は全部を知ろうと思ったら大変だよ。C 全ても含まれるし
かなり重複がある。それでついでに STL+boost 位は必要。
ただ、それ全てを知る必要は無いけどな。
boostはまだ標準じゃないから勉強は後回しでいいよね? MFCとATL覚えるのに手一杯でさ・・・
880 :
846 :2008/05/20(火) 23:14:47
色々アドバイスありがとうございました! fout.write((char*)&i, sizeof(i)); これでうまく行きました。 スタンダードMIDIファイルを吐くプログラムを作ってて、ビックエンディアンで並べないといけないところがあったのですが ss << p[3] << p[2] << p[1] << p[0]; みたいな感じで書いてなんとかなりました。 ありがとうございましたm(_ _)m
>>879 boost は便利なものがあるから、あることを知っていて何か
「これはあるべきだけど無い!」みたいなものがあったときに
探すと良いと思う。かなりの確率である。
boost 全てについて学ぼうなんて考えない方が良い。
>>879 tr1に入った奴位は覚えとけばいいんじゃね
shared_ptrとか便利だよ
vaultやsandboxまで手を付けるとキリが無くなるという
テンプレートでifとか制御文とか 作ってみたけどなかなかboostまでいかない どうしてなんだろう
boost::anyあたりなら俺でも読めたよ
>>884 心配するなって。ものによると思うよ。
自分に必要なものなら、これだ!ってわかるさ。
あと、比較的簡単に入れるのも多い。
ただ、初め何を言ってるのかさーっぱりのもある。
いやそうじゃなくて何もみないで boost:anyの関数名だけみて oreore:any作ってみたが 全然あっちの方がいけてるって話 発想レベルが腐ってるんだろうな
>>887 でも書いてみるってのはいいと思うぞ。
自分でやれば、Boostの実装がいいってのが実感できる。
ぱっと見でboostレベルの実装が思いつく奴なんてそういないだろ・・
質問です。 コピーコンストラクタで一部の値だけ新しい値を与えてオブジェクトを生成したいのですが、こういう書き方はアリ(普通に使うか)でしょうか? class Base { public: Base( int newID, const Base& rhs ) : m_id( newID ), m_param( rhs.m_param ){} virtual ~Base(){} private: int m_id; int m_param; }; class Derived : public Base { public: Derived( int newID, const Derived& rhs ) : Base( newID, static_cast<const Base&>( rhs ) ), m_name( rhs.m_name ){} virtual ~Derived(){} private: string m_name; }
それはコピーコンストラクタとは言わないけど、手法としてはありじゃね? 標準ライブラリでもlocaleでそういうことやっている。
boostで実装が想像すらできないのがis_base_ofね 親クラスの型なんてどうやってチェックしてんだかさっぱわからん
Visual C++なら__is_base_ofを使うだけ。 そのうちどこのコンパイラも似たようなものを用意するに違いない。
>893 boostはあらゆる環境で使えるわけだが、 VC++固有の話をしただけじゃ全然わかったことになってないぞ
そんな冗談を真に受けるなよ……。
896 :
デフォルトの名無しさん :2008/05/22(木) 13:20:28
C言語ばかりやってきてC++はあまり良く分かっていないんですが、 例外というのは関数の戻り値によるエラー処理と違ってどういうメリットがあるんですか? なんか例外はBasicのGoto文みたいで流れが読めなくて気持ち悪いんですけど。
>>896 戻り値の確認を忘れるヘマを避けられる。
あと、戻り値を持たないコンストラクタからも使える。
>>896 例えば
int foo() {
if (bar() == 失敗) return 失敗;
if (baz() == 失敗) return 失敗;
if (hoge() == 失敗) return 失敗;
return 成功;
}
のようなものを
void foo() {
bar();
baz();
hoge();
}
と書いて失敗を例外で投げればコードが簡潔
あとコンストラクタなどの戻り値を取れない関数でエラーを返すのに使ったり使わなかったり
899 :
デフォルトの名無しさん :2008/05/22(木) 13:42:21
>>897 「コンストラクタから例外を投げるな!」
って、どこかで聞いた気がするけど、そうでもないのか?
>>899 「デストラクタから例外を投げるな!」
の間違いでは?
>>899 例外安全を心掛けないと資源リークする可能性がやや上がるというだけ。
deleteとかを生で使うな、auto_ptr/shared_ptrとかvectorとかを使え、で大体済む話。
都市伝説が多い言語?
>>902 の次のようにしますってのもよい例には見えない。
まずfunction-try-catch使うとか、throw;書くとかして例外を投げなおせよ。
まぁ、確かに良い例じゃないね。 普通は↓だし。 struct foo { std::auto_ptr<A> a; std::auto_ptr<B> b; foo() : a(new A), b(new B){ ... } };
RAIIを徹底してればどこから例外が出ようと問題ないので 処理の流れとか気にしなくても良い
コンストラクタで例外が出る可能性のある処理を書くのが間違いなんじゃないの?
それは、状況次第。 コンストラクタで例外を発生させないためだけに、コンストラクタと それに続く処理を分けたメソッドを作るのは、俺はダサいと思う。
ばーかwwwwwwwwww
つうかRAIIしようと思ったらコンストラクタでの例外は避けられないだろ 絶対に確保に失敗しないリソースがあるなら別だけど
質問です(gcc 4.1.1)。ログを出力する簡単なクラスを作ろうと思い、 出力ストリーム(std::ostream &)またはファイル名(const char *) を引数に取るコンストラクタを作りたいのですが、どうやるのが一番スマートでしょうか? とりあえず以下のようにしてみたのですが、 class Logger { private: std::ostream *logOs; public: Logger(std::ostream &os = std::cout): logOs(&os) {} Logger(const char *file): logOs(new std::ofstream(file)) { if (!*logOs) { /* エラー処理 */ } } ~Logger() { delete logOs; } }; これでは不十分で、コンストラクタの引数が出力ストリームのときは デストラクタでlogOsをdeleteしないようにする処理も必要です(ダサい)。 また、デストラクタでdeleteすること自体もできればやめたいです。 そのためにはlogOsをポインタではなくstd::ostream自身にする必要があると思い、まず class Logger { private: std::ostream logOs; public: Logger(std::ostream &os = std::cout): logOs(os) {} }; とだけ書いてみたところ、以下のようなエラー(他にも色々)が出ました。 が、意味が分かりません。orz /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/bits/ios_base.h:779: error: 'std::ios_base::ios_base(const std::ios_base&)' is private グダグダと書いてしまいましたが、何かアドバイスがあればお願いします。
>>912 エラーの内容は、「std::ostreamのコピーコンストラクタは使用が禁止されているからlogOs(os)はできないよ」
前者のクラスの設計について思ったんだが、一つ目のコンストラクタではクラス外からオブジェクトを持ってきているのに
二つ目ではクラス内で完結していて、しかもデストラクタでdeleteしている。何故こんなに中途半端なのか?という疑問。
クラスを横断するオブジェクトを保持したいのならauto_ptrなりshared_ptrなりを使えば良いし、
そうでないならクラス内でヒープから持ってくるオブジェクトも完結させる。
>>912 直前で散々話題になってるのに・・・w
生のdelete使うなw
>どうやるのが一番スマートでしょうか?
まず、スマートポインタを使う。
俺ならファイル名貰うコンストラクタなんて作らない。
std::ostream&か、std::auto_ptr<std::ostream>を貰う。
>>912 class Logger {
std::ostream * pOs;
std::ostream & rOs;
public:
Logger(std::ostream & os) : pOs(NULL), rOs(os) {}
Logger(const char * file) : pOs(new std::ofstream(file)), rOs(*pOs) {}
~Logger() { delete pOs; }
};
とりあえずオリジナルのLoggerを尊重してみた。
ただ何かイマイチだね。うまく言えないけど。
そんなにスマートポインタいいかなあ
RAIIを使わないC++はC++じゃない、くらいに考えても良い
>>915 delete するかどうかのフラグを持ったスマートポインタを使えばいいのさ。
スマートさを追求したいならconst char *のコンストラクタない方がいいんじゃね?と ここまで読んで思った。 ostreamのポインタってすごく気持ち悪いの俺だけ?
920 :
912 :2008/05/23(金) 01:03:31
921 :
912 :2008/05/23(金) 01:12:50
>>915 なるほどです。あとは
>>914 さんが指摘しているように、
pOsをスマートポインタにすれば今のところ最もスマートな方法だと思います。
ストリームとファイル名の両方を指定可能にするには、
std::ostream * の使用は避けられないのかもしれません。
>>916 「そんなに」ってどういうこと?
最低限の auto_ptr を使うだけでも何か引き換えにするものがあるとでも言うの?
これでどうよ class Logger { std::ostream & rOs; public: Logger(std::ostream & os) : rOs(os) {} }; class FileLogger: public Logger { std::ofstream ofs; public: FileLogger(const char * file) : Logger(ofs), ofs(file) {} };
大きいサイズのメモリを確保するとき、 タスクマネージャーの空き容量より小さい値でも確保できないときがあります。 これは、メモリの断片化などで連続領域が確保できない。 ということでよろしいのでしょうか? また、これを回避して大容量の連続領域を確保する方法はあるのでしょうか? ちなみに、空き容量1.9GBで500MBの連続領域が確保できませんでした。 確保の関数はnewを使っています。 よろしくお願いします。
プロセス内のメモリ空間が断片化するほど、確保と解放してるの? 仮想記憶だからプロセス間での断片化は関係ないはずだが。
ヒープの上限が低く設定されているんだよ VC6ならプロジェクトオプションに /Zm何たら と指定すればいいんだ 僕は頭が悪いのにC++を使っているよ
927 :
912 :2008/05/23(金) 14:55:06
>>923 なるほど、継承を使ってostream &とofstreamを組み合わせるわけですね。
で、
>>915 と見比べながら考えていたら、
継承を使わなくても実現できるのではと思い、
class Logger {
std::ofstream ofs;
std::ostream &rOs;
public:
Logger(std::ostream &os): ofs(0), rOs(os) {}
Logger(const char *file): ofs(file), rOs(ofs) {}
};
としたところ、これでも動きました!
なぜ
>>915 を見たときに思いつかなかったんだろう?
ostreamとofstreamを混在させるという発想がなかった
のかもしれません。
ちなみにofsとrOsの宣言の順番を逆にしても、つまり初期化子を
rOs(ofs), ofs(file) としても動きました。ちょっと不思議です。
>>926 は問題外として、その環境じゃ確保できないんだろう
C++の問題というわけではないので、環境依存スレで聞いた方が良いよ
XPだと標準設定で512MBまでは確保できたと思うが、レジストリの値とか確認してみると良い
>>927 メンバ変数は宣言した順に初期化される。
初期化子の順番は関係ない。
templateな関数で文字列をtemplateとして使いたいんですができますか? template< const char* T > void basic_test( const char* test ) { puts( T ); // ファイル名 puts( test ); // 書き込み } int _tmain(int argc, _TCHAR* argv[]) { basic_test< "test.log" >( "test" ); return 0; } こんな感じで使いたい
やってみて出来たなら、君の環境では出来るということだろう。
934 :
912 :2008/05/23(金) 16:43:25
>>929 失礼、説明不足でした。
ofsとrOsの変数宣言の順番と初期化子の順番の両方を逆にしても
動いたということです。つまりrOs→ofsの順番にした場合、
Logger(const char *file): rOs(ofs), ofs(file) {}
というコンストラクタにおいて、rOs(ofs)が先に実行されるはずですが、
ofsが初期化されていないのに実行できるのかという疑問があります。
もしかすると、初期化における代入の依存関係を見て
ofsが先に初期化されたりするんでしょうか。
>>934 初期化リストの並びは初期化の順番に関係ない
あくまでもメンバ変数の宣言順に実行される
>>935 ちゃんと読んでやれよ・・・w
>>934 普通に未初期化のまま、ofsの参照が渡ってる。
あまり良くない方法ではあるものの、
未初期化のインスタンスの
メンバにアクセスしなければ問題無い。
なので、そのLoggerの実装なら大丈夫。
937 :
912 :2008/05/23(金) 21:12:07
>>936 > 普通に未初期化のまま、ofsの参照が渡ってる。
色々試してみて理解できました。
初期化子においてrOs(ofs)が先に実行される時点では
ofsは存在さえしないと思っていたんですが、存在はしていて、
ただし初期化されていない(=引数なしでコンストラクタが呼ばれてofsが生成された)
状態なんですね。
>>937 いや、ofsのコンストラクタは呼ばれてない。
メモリが確保されてるだけ。(アドレスは確定してる)
未初期化オブジェクトの参照を取る事って、規格的に許されてるんだっけ? 未定義動作な匂いがプンプンするんだが。
参照だけなら多分大丈夫。何か呼び出したりしたらアウト。 キモイから俺は参照もしないけど。
未初期化で触るのが嫌ならboost::base_from_memberでも使えばよい。
というか折角分離したのに何故わざわざくっつけるんだ?
>>927
942 :
912 :2008/05/23(金) 22:03:38
>>938 なるほど、そういうことですか。
それなら処理時間のオーバーヘッドもほとんどないですね。とはいえ、
>>940 確かにキモいので私も実際にはofs→rOsの順番にしときますが。
>>941 >というか折角分離したのに
あ、俺もそれ思ったw
944 :
912 :2008/05/24(土) 10:51:36
一つのクラスにまとめた理由は、ストリーム、ファイルの場合とも ファイル名を引数にとるコンストラクタ以外のインタフェース(メソッド関数) が実装を含めて同じだからです。 逆に分離した場合、FileLoggerの方で記述されるのは ・メソッド変数ofsの追加 ・ファイル名を引数にとるコンストラクタの追加 のみです。これだけのために分離するメリットを感じませんでした。 一つのクラスにまとめるデメリット、分離するメリットがあれば教えてください。
>>944 分離してあればファイル以外の ostream に対しても同じクラスがそのまま使える。
(同じことだけど、)混ぜてあると別の ostream に対して使う場合に ofstream が無駄になる。
>>944 ostream
ofstream
ostringstream
Logger
FileLogger
MemoryLogger
void f1(Logger& log){
...
}
void f2(){
FileLogger log("a.log");
f1(log);
}
void f3(){
MemoryLogger log;
f1(log);
}
>>944 標準出力だろうがファイル出力だろうがstring型の変数への出力だろうが
もっと極端なこと言えばFTPでファイルうpする処理だろうが、
何かを出力する処理ならばostreamに対応した処理を1回書けばいい、
っていうのがostreamの理念。
その関数を呼ぶ側であらかじめ出力したい対象に対応する
ostream(の派生クラス)を勝手に作っておいて、
osteream対応関数を呼び出せば、
あとはostream(の派生クラス)が良きに計らって
実際の出力対象に出力してくれてる。
948 :
912 :2008/05/24(土) 11:46:19
なるほど、メモリなど様々な種類のものに対応するために拡張しようとしたとき、 一つのクラスにまとめているとムダなメンバ変数がどんどん増えてしまう (もしかするとメンバ変数も増えるかも)ので、クラスを分類しておく方が いいわけですね。 (LoggerとFileLoggerだけを例にとってもofstreamがムダになってる。)
なんだかんだで理解できてるのは良いね。
950 :
912 :2008/05/24(土) 11:55:17
>>947 ん?そう考えていくと、ostream自身にログを出力するメンバ関数を
追加したくなってきますね。そうすればofstreamでもstringstreamでも
そのログ出力関数をそのまま使えるし。
(つまりFileLogger, StringLoggerのような派生クラスを作る必要がない。)
そういう考えって変?
# 変じゃないとしても、実現方法が分からない…。
自作クラスにstreamのインターフェースを搭載するのにboostって使える?
>>950 うん、正直なくてもいいと思う。
Loggerを"利用する側"でファイルに出力して欲しいなーと思ったときは
std::ofstream ofs(filename);
Logger logger(ofs);
すればいい。
Logger側で何に出力してるかを気にする必要がなくなる。
出力するだけなら生でもいいけど、対象特有の加工をしたかったら やはり派生してメンバを追加したくなるな。 FileLoggerに最大出力行数を設定して行が溢れたら自動的に ログファイルの先頭から削除とか。 実際にするかどうかはともかく、将来の拡張に柔軟というのは 考慮に値する特性だと思う。
>>950 役割を考えるとそれはちょっと違うかな。
ofstreamはストリームで、ログはストリームとは限らないだろう?
ログを出力先はファイルでもメモリでもなく、
システムに用意された関数かもしれない。
Loggerの役割は、ログを出すこと。
ostreamに出力するのも、ログ出力の実装の一例に過ぎないと考えた方がいい。
コンストラクタ内から、他のクラスなどに対して this ポインタを渡す、ということは可能でしょうか
可能。やってみればわかる。注意事項はイロイロあると思うけど。
957 :
912 :2008/05/24(土) 18:01:44
Rubyとかだと既存クラスに簡単にメソッドを追加できるので
>>950 のような発想をしたんですが、
基本的には
>>952 のような方法で利用すれば十分ですよね。
と考えると、
>>927 のようにファイル名を引数にとるコンストラクタまで
用意するのは車輪の再発明っぽくてあまり美しくないなあと思いました。
>>953 ,954
ログ出力の実装をostreamの派生クラスによって変えたいかもしれない、
ログ出力の適用先がostream以外にもあるかもしれない、ということですね。
参考になりました。
>>956 返信ありがとうございます
Javaで駄目だと言われていたので気にしていたのですが…
注意事項というのは、コンストラクタ抜ける前にポインタを使われたりすると問題が起きる、といったようなものですか?
>>959 Javaで駄目だというのも同じ理由。
初期化が完了していないため、
そのオブジェクトのメソッド(C++ではメンバ関数)などを呼ぶと
予期せぬ状態になる。
逆にいえば、JavaでもC++でも、そのオブジェクトを扱わずに
ポインタ(or参照)を保存するだけに留めるなら問題無い。
ちなみに
>>936-940 n で同じ話が。
アンチ C++ で有名な人ってどんな人がいますか?
ジャバ・ダ・ヤッパ
C#が好きって言いたいのか
.net 2003の_com_error& では代入演算子の中でコンストラクタを呼び出してます。 inline _com_error& _com_error::operator=(const _com_error& that) throw() { if (this != &that) { this->_com_error::~_com_error(); this->_com_error::_com_error(that); // ココ } return *this; } よく複数のコンストラクタで同じ処理をしたい場合、コンストラクタから 別のコンストラクタを呼び出すことはできないから初期化関数を 作ること、とされていますが、上記コードがOKならばコンストラクタから 別のコンストラクタを呼び出してもいいように思えます。 実際.net 2003でやってみましたが、問題なく動作します。msの独自仕様なんでしょうか?
970 :
969 :2008/05/25(日) 09:42:46
BCC5.5.1ではthis->があるとビルドエラーになりました。 this->をはずすと上手く動いているように見えます。 テストコードはこんな感じです。 class Cls { public: Cls(void){printf("ctor\n");} Cls(int i){ Cls::Cls();}//ココ }; int main(void) { Cls c; // ctor Cls c2(1); // ctor return 0; }
少なくともbccのほうのコードは、一時オブジェクトが作られて、そのコンストラクタが呼ばれてるだけだと思うけど。
>>970 とりあえず、コンストラクタでthisのアドレス出してみたら?
std::cout << "ctor " << this << std::endl;
>>970 以下のようにして、thisとkの値をモニタしながらステップ実行してみよう。
class Cls
{
private:
int k;
public:
Cls(void)
{
printf("ctor\n");
}
Cls(int i)
{
k=3;
Cls::Cls();
}//ココ
};
974 :
973 :2008/05/25(日) 10:45:22
一行抜けてた class Cls { private: int k; public: Cls(void) { k=5; printf("ctor\n"); } Cls(int i) { k=3; Cls::Cls(); }//ココ };
>>969 placement newを使う方法ならどのコンパイラでも使える。
#include <new>
T& T::operator =(const T& y)
{
if (this != &y)
{
this->~T();
new(this) T(y);
}
return *this;
}
しかし、コンストラクタの中で例外が起こると非常にまずい
(thisがデストラクタされて状態不定のまま)などの理由で勧められない。
代入演算子をコピーコンストラクタで実装したいという目的に限れば、
Exceptional C++でも紹介されているswapを使う方法がいい。
//その1
T& T::operator =(const T& y)
{
T t(y);
swap(t); //Tのメンバ関数として作っておく
return *this;
}
//その2
T& T::operator =(T y)
{
swap(y);
return *this;
}
Tのコピーコンストラクトが高コストの場合は↓ T & operator =(const T & t) { if(this != &t) { T(t).swap(*this); } return *this; }
977 :
969 :2008/05/25(日) 14:06:49
>>971 、972、973
>少なくともbccのほうのコードは、一時オブジェクトが作られて、そのコンストラクタが呼ばれてるだけだと思うけど。
そうでした orz bcc、vc7.1とも。
vc7.1でthisをつけた場合は一時オブジェクトは作られず、自身のコンストラクタ呼び出しになりました。
>>975 placement newはできるんですね。
976が975のその1より低コストというのは、
if(this != &t)が効いてるんですか?それともT(t).swap(*this);の方ですか?
また私はその1でもif(this != &y)にすべき気がするんですが。。。
重要なのは (const T & t) のところだと思うけど。
>>977 > vc7.1でthisをつけた場合は一時オブジェクトは作られず、自身のコンストラクタ呼び出しになりました。
は標準C++的にはアウトだと思います
ISO/IEC 14882 Second edition 2003-10-15 にも
12.1 Constructors
Constructors do not have names.
とあります。コンストラクタには名前がないのです。つまり明示的に呼び出すことは出来ない
ググれ 「コンストラクタからコンストラクタを呼び出す C++」
Javaのthisみたいなのが欲しいお
ただのthisならC++にもあるから、983が欲しいのは内部クラス絡みのthisか?
自身のコンストラクタのオーバーロード呼び出しのthis()だと思う。 class A { A(){ this(10); } A(int n){} }; //C++的に書くと↓のようなもの struct A{ A():A(10){} A(int n){} };
986 :
969 :2008/05/25(日) 16:08:21
>>978-980 T t(y);
swap(t);
より
T(t).swap(*this);
の方がコピー回数が少ないのかなと思いましたが、そんなことないですよね?
>>981 ありがとうございます。名前がないというのは面白いですね。
>>983 欲しいです。初期化子を重複して書かないといけないのが嫌なんですよ。
初期化子を別の所にマクロとして書いてそれを使ってるんだが それじゃだめなの?
>>987 メンバ追加したときに変更箇所が離れてると面倒
ということでC++0xマダー?
そろそろ次スレの季節だよな
990 :
デフォルトの名無しさん :2008/05/25(日) 20:11:46
インスタンス変数のsizeofをとるだけでthis必須はアフォだよな
static関数を内包する構造体はPOD型として認識されますか?
ええ
?かすまれさ識認てしと型DOPは体造構るす包内を数関citats
仮想関数でなければ問題なくね?
A POD-struct is an aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-defined copy assignment operator and no user-defined destructor. Similarly, a POD-union is an aggregate union that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no userdefined copy assignment operator and no user-defined destructor. A POD class is a class that is either a POD-struct or a POD-union.
An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).
cstdlib
cstdlib
,===,====、 _.||___|_____||_ .. / /||___|^ l .. (・ω・`)//|| |口| |ω・` ) . ./(^(^ .//||...|| |口| |c ) ... / // ||...|| |口| ||し 新スレです ....... (・ω・`) //.... ||...|| |口| || 楽しく使ってね /(^(^ // .... .||...|| |口| || 仲良く使ってね "" :::'' |/ |/ '' " ::: ⌒ :: ⌒⌒⌒ :: "" ` :: ,, ::::: ,, ; ̄ ̄ ̄ "、 :::: " ,, , ::: " :: " ::::
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。