STLつかうと一気に実行ファイルサイズが10倍に?!
環境によるだろ。 俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力 ランタイムを使用するようにして使っているが、例えばstd::vectorを 使っても使わない時と比べ10Kほどしか増えない。
すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいの?
#include <stdafx.h> 後氏ね。
>>15 言葉が悪いな。それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。
>>11-15 ,17
乙
後半(
>>6-10 )は携帯から書き込んだわけだが…スレ立ての時に限っては
もうちょっと連投規制を緩くして欲しいな。
19 :
デフォルトの名無しさん :2005/08/16(火) 01:27:43
20 :
デフォルトの名無しさん :2005/08/16(火) 04:27:22
wstringの文字列で、指定したn文字目の文字が何バイト文字かを調べたいのですが どうしたらよいでしょうか。
n文字目をいきなり判定することは出来ない。 先頭から順番にチェックしていくしかない。
23 :
デフォルトの名無しさん :2005/08/16(火) 09:51:56
あるだろその関数・・・
wstringならそもそも格納が文字単位なので 普通にインデックスとればそれが文字位置。 あとwstringはワイド文字で格納されているので あえて言うなら全部sizeof(wchar_t)バイト文字。 その文字がマルチバイト文字に変換して何バイトかっていうのなら エンコードによるし。UTF-8で日本語なら3バイトが多いとか。
26 :
デフォルトの名無しさん :2005/08/16(火) 13:00:48
ウインドウ内で画像を移動させたいのですが何度やっても上手くいきません。 色々調べてみましたが結局詰まってしまったのでご助言をお願いします。 以下描画部分(メッセージ処理の一部)を書きますが、それ以外で必要な部分があれば言ってください。 case WM_CREATE: SetLayeredWindowAttributes(hWnd, RGB(255, 0, 255), 0, LWA_COLORKEY); //紫を透明に SetTimer(hWnd,1,100,NULL); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); ExtFloodFill(hdc, 1, 1, RGB(255, 255, 255), FLOODFILLSURFACE); hbmp = (HBITMAP)LoadImage(hInst, "BITMAP1",IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); hdc_mem = CreateCompatibleDC(hdc); SelectObject(hdc_mem, hbmp); StretchBlt(hdc, POSX, 0, 100, 100, hdc_mem, 0, 0, 100, 100, SRCCOPY); //POSXは変動 EndPaint(hWnd, &ps); break; --続く
27 :
デフォルトの名無しさん :2005/08/16(火) 13:01:52
続き-- case WM_TIMER: hdc = BeginPaint(hWnd, &ps); ExtFloodFill(hdc, 1, 1, RGB(255, 255, 255), FLOODFILLSURFACE); hbmp = (HBITMAP)LoadImage(hInst, "BITMAP1",IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); hdc_mem = CreateCompatibleDC(hdc); SelectObject(hdc_mem, hbmp); StretchBlt(hdc, POSX, 0, 100, 100, hdc_mem, 0, 0, 100, 100, SRCCOPY); //POSXは変動 EndPaint(hWnd, &ps); break; 紫を透明色にし、ウインドウのメニュー・枠線を消して画像だけを表示させることをしようとしています。 WM_TIMERは何度も通っているのを確認、POSXの値は変わっています。 一度WM_PAINTで描画するとどうやってもウインドウ内の位置は変わらないようです。 環境はWindowsXP VC++.NETです。
28 :
デフォルトの名無しさん :2005/08/16(火) 13:07:41
>>24 とりあえずatとかsubstrでn文字目を取り出すことができるっぽいことは発見しました。
実は簡単なテキストエディタを作ろうと思っているのですが、
折り返し部分(ウィンドウ幅に合わせて自動で折り返したい)やカーソルの指している部分が
何バイト文字で先頭から何ドット目であるかなどを調べて、
その部分で文字列を分けたり挿入したりしたいです。
結局そういったことをするにはテキストを何型で持ってればよいのでしょうか。
あちらを立てればこちらが立たずという感じでワケがわからなくなってきました。
>>29 誘導ありがとうございます。
そちらに書いてきます。
>>28 wstring で持ってて「こちらが立たず」という例は、どれだ?
誘導先のスレにて解決できましたので報告までに。
>>26 WM_PAINTに応答するとき以外はBeginPaint, EndPaintを呼んでは駄目だ。
どうせ更新領域が空でなにも描画されてないんだろ。
34 :
28 :2005/08/16(火) 14:19:15
>>31 もちろん私が知らないというだけできちんと方法はあるのかもしれませんが、
例えばマウスクリックした位置にエディタのカーソル(キャレット)を移動し、
そこに文字列を挿入したいとします。
マウスの座標を取得し「その座標の位置にある文字が何文字目であるか」が
取得できればinsertとか使えると思うのですが、
wstringの場合、文字列の先頭から1バイト文字かマルチバイト文字かを判断し
1バイトなら8ドット、2バイトなら16ドットのように足していって
座標値を割り出すことができないのでマウス座標との判定ができなそう、、、など。
あとはIMEで漢字変換したとき、WM_CHARが連続して流れてくるみたいなんですが、
WPARAMをwstringの文字列に突っ込んでもうまくいかないようで、
文字化けしたようになってきちんと表示できませんでした。
stringの場合はそのまま突っ込んでもきちんと表示できていたので、
じゃあstringを使おうかなと思ったのですが、
これだと今度はマルチバイト文字を使った時に「文字単位」で操作できないし、、、
などです。
35 :
デフォルトの名無しさん :2005/08/16(火) 14:26:47
>34 そんなことしなくともテキストエディタ作ってやればいいんじゃないかな? SetDlgItemTextで貼り付けてやって、そいつを編集後、 GetDlgItemTextで取得 テキストエディタなら入門本にいくらでもある それとも、テキストエディタじゃ駄目なのかな?
36 :
28 :2005/08/16(火) 14:31:16
>>35 ゲーム作ろうと思ってるので、それほど高度なものは必要ないのですが、
Windowsのコントロールの貼り付けとかせずに自前のものを作りたいのであります。
stringでいいんじゃね? っていうかGetTextExtentPoint32使えばいいんじゃね? GetCharWidth32とかも使えるんじゃね?
38 :
デフォルトの名無しさん :2005/08/16(火) 18:20:24
もの凄いくだらない質問なのですが、 配列を、ある地点から降順で検索するときの、「スマートな」書き方があれば教えて頂けないでしょうか (ある地点が0(先頭)の場合もあります)
39 :
38 :2005/08/16(火) 18:29:21
Cスレにすべきだた…私のスマートじゃ無さそうなのはこんな感じです なんか上手い人ならfor文だけでできそうな気がするんです if( a_position == 0 ) //a_position : インデックスのある地点 hoge( *array ); else for( int i = a_position; i >= 0; --i ) hoge( array[i] );
[begin, a_position + 1)で探索するだけやがな…
検索?用語は正しく使ってくれ…
42 :
38 :2005/08/16(火) 18:50:01
>>40 降順でやりたいので…
>>41 手元の教本(英語)だとretrieveとあったので
スレ違いっぽいですし質問撤回します
>>36 高度なものが必要ないなら、なおさらOSやライブラリに任せるべきじゃないの?
47 :
28 :2005/08/16(火) 21:19:40
>>37 GetTextExtentPoint32とか調べてみたのですが
描画もフォント作成もDirectXをつかうのでhdcを渡さないといけないのが何か。。。
なのでやはり先頭から順にバイトで調べる方法が使える型の方がいいのかなーとか
考えてるんですが整理できないです。
>>44 文字の大きさ指定して等幅フォントつかったとしても
バイト数だけでは判断できるとは限らないって事でしょうか?
例えば2バイト文字でも半角幅の文字がある、とか。
>>45 機能面で高度なもの(アンドゥとかコピペとか)はいらないのですが、
DirectXと標準コントロールを混在させると画面がちらついたり
するらしいし、見た目も気に入らないのでちょっと自作に拘りたいのです。
>47 文字を自前描画しているなら、wcharのあるコードポイントが 何ドットを占めているかは簡単に調べられるだろう。 あとは、だんだん延ばして(減らして)いって変換するだけではないのか?
49 :
28 :2005/08/16(火) 22:51:35
>>48 よくわからないのですがwcharってwstringみたく半角アルファベットとかでも
マルチバイトで持ってるんじゃないんでしょうか?
簡単に調べられるというのは具体的にどうやって調べればよいでしょうか。
自前描画といっても、フォントと文字サイズを指定してconst char*を渡すと
勝手に書いてくれるDirectXの関数を使っているだけなのですが、、、
>>47 ,49
さんざん言われてるキーワード「エンコーディング」ぐらい調べてから出直せ。
52 :
28 :2005/08/16(火) 23:23:06
>>50 自前描画してるなら~と言われたので、
描画はただDXの関数使ってるだけだしそれがドット数調べたいのと
何の関係があるのかなーと思いつつ説明しただけでして、
あとはDirectXは標準コントロールを使えない理由として
挙げただけですからDirectXスレは全然関係ないと思うのですが。
>>51 エンコーディングって言うと文字コードの話でないでしょうか?
型の事とはまた少し別なような気がするのですが。。。
文字列を、DirectXの関数(どーせGDIラッパのID3DXFontだろうけど) つかって描画をしている。その(部分)文字列の長さがほしい。 なら、当然DirectXスレか、3歩譲って、Win32APIスレだろ。
>>52 何が関係が有るのか無いのか判断できるほどオマエは賢くない。
もう一度言うが、まずはここで言われたことを自分で調べて、理解し、
それでもC++に関する質問が残っていればまた来い。
55 :
28 :2005/08/16(火) 23:31:09
文字列操作とか型の相談でして 別に描画に何を使おうが関係ない話だと思うんですが。
>>55 オマエが思ったことなら正しいとでも言うつもりか?いいかげんにしろよ。
wstring使え。環境との間で問題が出るのは、wstringの使い方が間違ってる。以上。 これでいいのか?
58 :
28 :2005/08/17(水) 03:49:09
そんなにここで質問するのが気に入らないんですか? 気に入らないなら見なきゃいいじゃないですか。
>>28 はプログラムのお勉強の前に
日本語の読み取り能力とコミュニケーション能力を養え
そして誰一人として納得させられる回答を提示できないという事実。 それどころか質問の意図すら汲み取れず しまいにゃ意味不明な逆切れで全然関係ないスレに誘導。
回答の意図を汲み取れない人発見。 負け犬の言い訳はいつも同じだな。
>>34 >wstringの場合、文字列の先頭から1バイト文字かマルチバイト文字かを判断し
>1バイトなら8ドット、2バイトなら16ドットのように足していって
>座標値を割り出すことができないのでマウス座標との判定ができなそう、、、など。
もちろんその方法では出来ない。
wchar_tの幅(ピクセル数)を得る標準的な方法は存在しない。
よってスレ違い。
>あとはIMEで漢字変換したとき、WM_CHARが連続して流れてくるみたいなんですが、
>WPARAMをwstringの文字列に突っ込んでもうまくいかないようで、
>文字化けしたようになってきちんと表示できませんでした。
IME、WM_CHAR、WPARAMと言っている時点で当然スレ違い。
>stringの場合はそのまま突っ込んでもきちんと表示できていたので、
>じゃあstringを使おうかなと思ったのですが、
>これだと今度はマルチバイト文字を使った時に「文字単位」で操作できないし、、、
>などです。
できないのではなく、やりにくいだけ。
マルチバイト文字をどう判別したらいいかはエンコーディングや環境に依存する。
よってスレ違い。
このようにスレ違いのオンパレードにもかかわらず、多くの人が親切にもヒントを与えてくれている。
>>28 はもう少し自分で考え、分からない事を明確にした上でもう一度質問してくれ。
どうやるか迷っているのは分かるが、決めるのはあなただ。
本買って勉強しる
スレ違いって言われた時点でとっとと移動しないところが一番悪いな。 それは~の話だって言われてもググりもせずに関係ないとか言って無視してるし。
UTF8とかシフトJISはstd::string?wstring? どっちにしてもatとかfindは機能しなくない?
DXスレに誘導してた馬鹿が一人で頑張ってますね。
そもそもテキストエディタを作るのに、無理にbasic_stringを使う必要はない。 適していると思うデータ構造を自分で選んで使いなさいw
それを決めあぐねて助言を求めてるんだろう?
エディタの人ではないのだが。 いつもユニコードに変換してCStringとかBSTRで処理してるから 標準ライブラリ使ってる人はどうしてんのかと思っただけ
>>65 UTF-8は普通UCSに戻して処理するだろ。
SJISは場合によっては16bit化してwstringにつっこむこともある。
71 :
65 :2005/08/17(水) 14:00:22
了解。
あとはマルチバイトに対応した文字処理関数とか文字列クラスを自分で作るくらいかなぁ。
73 :
28 :2005/08/17(水) 17:05:29
えー、なにやら偽者が出てますが、テキストはwstringをとりあえず使っとけ ということだったのでとりあえずそれを使うことにしました。 あと文字幅を調べるのは教えていただいたGetTextExtentPointを使って調べる事にしました。 これはhdcを作ったりDirectXに渡すのと同じフォントを重複して作るのが 気持ち悪くてなんとなく使うのが嫌だったのですが、 これだと太文字使っても文字幅とれるみたいで予想外に便利でした。 長々とお世話様でした。
まったく関係ない話だが、 マルチバイト文字を操作する場合、対応するイテレータ ( Readable ( Forward or Bidirectional ) Traversal Iterator) を最初に作成しておくと楽。 特に MS系コンパイラのマルチバイト文字列を扱う関数なんかは、 1文字を int で要求することが多いので、dereference で int を返すようなモノを 作成しておくと、後々便利なことも多い。
なるへそ
マルチバイトってBOMあるの?
これもどうでもいい話だけど、Boost.Regex が ICU に対応したらしい。
ここは相談スレだから関係ない独り言はスレ違いです。 はやくDXスレに行って下さい。
>>76 Unicodeもマルチバイトだって事を知らないの?
>>74 Bidirectionalって可能なの?
……一文字戻るのに定数時間で終わらなくてもいいなら可能かな?
>>81 UTF-8 なら、1文字進めるのとほぼ同コストで可能。
SHIFT_JIS なら、MSコンパイラには _mbsdec がついてくるけど、
文字列の先頭位置へのポインタを要求するので、こちらは線形時間が必要。
なるほど、UTF-8は判別できるようになっているんですね。 thx.
EUCなら定数時間で判別できるのにねぇ。 SJISでも先頭からではなく、遡るアルゴリズムならかなり改善されるけど_mbsdecはどうなんだろ。
>>84 CRTのソースを見る限り遡ってるみたいよ。
2バイト前がマルチバイト文字1バイト目でなければ、前の文字は確実に1バイト文字なので、1バイト戻る。
以降、マルチバイト文字1バイト目でないものが奇数バイト前に見つかれば、2バイト戻る。
偶数バイト前に見つかれば、1バイト戻る。
インデントに全角空白を使ってますがご容赦を class House{ struct Hage{ }; class Oil{ public: Hage* hage_generator(); }; Oil oil; public: void hoge(){ Hage* wonderful_hage = oil.hage_generator(); } }; Hage* House::Oil::hage_generator(){ return new Hage; } クラス内クラスなんですが、これはコンパイル通りませんでして、解決には hage_generatorをclass内で記述するか、Hageの宣言をHouseの外に出せば良いわけですが、 それ以外の方法でどうにかならないでしょうか Houseでしか使えないHageを、出来ればHouseの外に出したくないんです
>>86 House::Hage* House::Oil::hage_generator(){
^^^^^^^
>>86 return new House::Hage;
^^^^^^^
書き忘れ。ここも。
>>88 お付き合いありがとうございます
実はそれも試したのですが、Hageはprivateだからダメよと窘められまして
もしかしてコンパイラのせいなんですかねぇ、規格斜め読み中です
>>89 おお、そちらはやってませんでした
やっぱり通らないのですが、恐らく
>>89 氏の環境では通っていると思いますので
うちのコンパイラが古いせいっぽいですね
重ねて感謝です
92 :
デフォルトの名無しさん :2005/08/18(木) 21:35:33
hageにかつらをかぶせたらprivateになった
93 :
デフォルトの名無しさん :2005/08/18(木) 21:51:47
class Hage{ friend class House; //以降全てprivate private: ・ ・ ・ >Houseでしか使えないHageを、出来ればHouseの外に出したくないんです つりか・・・
hook 関連でSTLちっくに整理されてるライブラリーってないの?
派生クラスでオーバーライドした仮想関数内で、delete *this;としたい状況にあるんですが、 派生クラスのコレクション(list<Base*>型)から削除するのが問題で、どのように書いたらいいのか困っています。 // 考えてみた方法1(Baseにコレクションを持たせるのはどうか?) class Base { public: virtual ~Base()=0; virtual void F()=0; static list<Base*> obj_; }; class Derived : Base { public: void F() { obj_.erase(find(obj_.begin(), obj_.end(), this)); } };
96 :
95 :2005/08/19(金) 15:22:03
// 考えてみた方法2(オブジェクト毎に関数ポインタを持つオーバーヘッドが気になる) class DoSomething { public: void Unregister(Base*); void Action() { obj_.push_back(Derived<DoSomething>(&DoSomething::Unregister)); //以下略 } private: list<Base*> obj_; }; template <class Manager> class Derived : Base { Derived((typename Manager::*Unregister)(Base*)) : Unregister_(Unregister) {} void F() { (*Unregister_)(this); } private; void (typename Manager::*Unregister_)(Base*); }; どういう設計が良いのでしょうか?
質問の下手なやつばかりだなあ
>>95 何がしたいかわからんが、Baseに任せた方がいいんじゃない?
class Base {
public:
virtual ~Base() { obj_.erase(find(obj_.begin(), obj_.end(), this)); }
virtual void F()=0;
static list<Base*> obj_;
};
class Derived : Base {
public:
void F() { delete this; }
};
100 :
95 :2005/08/19(金) 16:23:41
>>99 すみません、仮想デストラクタをDerivedクラスでオーバーライドした場合でも、基底クラスのデストラクタはちゃんと呼ばれるんですか?
やりたかったことですが、
本来、list<Base*> obj_は継承階層にあるクラスとは関係ないクラスが持つもので、
継承階層にあるクラスからobj_へのアクセスが、循環依存?になるんじゃないかと設計に困りました。
101 :
95 :2005/08/19(金) 16:33:01
あ、95の例は、 list<Base*>::iterator it = find(obj_.begin(), obj_.end(), this); delete *it; obj_.erase(it); じゃないとだめですね。
>>100 仮想デストラクタはもちろんトップレベルまで順次呼ばれる
循環依存? まだ何を問題にしているのかわからん
103 :
95 :2005/08/19(金) 16:42:21
>>102 >> 仮想デストラクタはもちろんトップレベルまで順次呼ばれる
なるほど
>> 循環依存? まだ何を問題にしているのかわからん
まず、
>>95 の例は、Baseがstaticでコレクションを持つことに疑問を感じます(ポリモフィズムを利用するクラスが持つべき)。
ポリモフィズムを利用するクラスがコレクションを持つことになると、
>>100 の最後の1行。
そこで考えたのが
>>96 の例です。
>>95 うーん、そういう設計の問題って、ソースに現れるようなものだけを提示しても仕方ないと思うよ。
そもそも、どういう目的でコレクションを使うのかとか 格納されるオブジェクトは何なのか(なぜ派生するのか) どういうときに削除したいのか その辺を説明して欲しいな
>>95 delete thisは避けて
listを持っているクラスが中のインスタンスもろとも消すのが適当だと思う
たとえばbool delete_meとかいうフラグを立てておくとか、
list経由でアクセスされる関数において削除要請を意味する値を返すとか。
コンテナに入ったオブジェクトが自殺したいってことかな? ならowner(listを持っているオブジェクト)に削除メソッドDeleteを持たせ 格納されたオブジェクトはownerへのポインタを持って、owner->Delete(this); だろうなあ。 ただこれを呼んだ後returnするまでが危ないっていうなら、Delete()では list_からdelete_list_に移し変えるだけにして 各オブジェクトの呼び出しが終わったらdelete_list_を一括deleteとかかね 参照カウントで同様の結果を得る方法もあるな
108 :
95 :2005/08/19(金) 20:53:19
>>106 なるほど、理にかなってると思います。
>>107 Ownerクラスのあるメンバ関数内ではDerived::F()の呼び出し。
Derivedクラスのあるメンバ関数内ではOwnar::Delete()の呼び出し。
両方のクラスに、相手クラスの関数名を記述しあうことになり、気持ち悪さを感じるんですが、
その辺は、気にしなくてもいいことなんでしょうか。
「listへ格納するクラス」に削除フラグを返す関数を書いて、「listを保持・使用するクラス」から削除する事にします。
レス下さった方、ありがとうございました。
>>108 終わったみたいだけど
>両方のクラスに、相手クラスの関数名を記述しあうことになり、気持ち悪さを感じるんですが、
直接参照するのがいやなら、インターフェイスとなる抽象クラスを間にかませば良いんじゃない?
この質問後をたたないな。。
実行速度について質問があります Microsoft VisualC++6.0にて開発しています。 ファイルの読み込みについてなんですが fstream経由で読み込むのと完全にC流で読み込むのではC流で読み込んだ方が 早い気がするんですが常識ですか?
>>111 ライブラリ次第。
VC6.0付属のやつはfopen系使って実装されてるので
fstreamのオーバーヘッド分遅くなる。
まあ、画期的な技術が開発されない限りは、 HDDのアクセス速度 >> fstreamやfopenのオーバーヘッド であるのだろうけどね。
継承と前方宣言について質問があります。 Aを継承したBというクラスを作ろうとして、 B.hのファイルでclass A;というプロトタイプ宣言をしたのですが、 コンパイラ エラー C2504 'class' : 定義されていない基本クラスが宣言されています。 と言われ、コンパイルできません。継承の対象クラスは実体を宣言しないとだめなのでしょうか?
>>114 そのとおり
クラスが'定義'されていないと継承できない
116 :
111 :2005/08/20(土) 00:45:18
>>112 >>113 即レスありがとうございました
fstreamとfopen両方の関数を適時つかえるようにするといった対処をすることにします
117 :
114 :2005/08/20(土) 00:52:03
>>115 即レスありがとうございます。
ではそういう場合どのようにコーディングするのですか?
同じファイルに継承したクラスを記述するしかないのでしょうか。
>>117 class Aなら a.hに書いて b.hでinclude "a.h"じゃろ
>>118 たしかにその方法でできるのですが、
そうなるとmain.hのほうで宣言していた
#include "a.h"
#include "b.h"
のところで
コンパイラ エラー C2011'identifier' : 'type' 型の再定義
識別子が既に type として定義されています。このエラーは、タイプ ライブラリを同じファイルに 2 回以上インポートした場合にも発生します。
のエラーがでてしまいます。これはb.hだけインクルードすればよいのですか?
#ifndef #endif
122 :
114 :2005/08/20(土) 01:13:09
>>120 即レスありがとうございました。
ググってきます。ノシ
123 :
114 :2005/08/20(土) 01:29:13
>>115 ,118,120,121
問題解決できました。
親切な回答ありがとうございました。
124 :
デフォルトの名無しさん :2005/08/20(土) 02:28:09
メンバ関数へのポインタをSTLを使って管理したいのですが、 文法上 どうかけばいいのかわかりません。 現在 CGame { public: static void Test(); }; vector< void (CGame::*)() > g_vFuncTable; g_vFuncTable.push_back( &CGame::Test ); と コンパイルしてみたところ コンパイルエラーがでます。 代入が悪いのか、宣言が悪いのか、教えてもらってもいいでしょうか?
何をやったらどんなエラーが出たわけ?
>>124 メンバ関数の型は static かどうかで変わる。
その例だと、 CGame::Test の宣言が悪い( static が要らない)可能性が高いな。
127 :
124 :2005/08/20(土) 02:46:49
>>125 上記のソースコードをコンパイルしたところ
g_vFuncTable.push_back( &CGame::Test );
のところで
以下のエラーがでました。
error C2664: 'push_back' : 1 番目の引数を 'void (__cdecl *)(void)' から 'void (__thiscall CGame::*const & )(void)' に変換できません。 (新しい機能 ; ヘルプを参照)
理由: 'void (__cdecl *)(void)' から 'void (__thiscall CGame::*const )(void)' へは変換できません。
この変換が可能なコンテキストはありません。
エラー内容が理解できないので、対処ができません。
128 :
124 :2005/08/20(土) 02:58:55
>>126 CGame::Test の static 修飾子をはずしたら無事コンパイルできたのですが、
g_vFuncTable.push_back( &CGame::Test );
の次の処理
g_vFuncTable.at(0)();
の部分で
error C2064: 関数ポインタとして評価されない式を使って、関数を呼び出そうとしました。
という コンパイルエラーがでてしまいました。
g_vFuncTable 変数を使って 代入した CGame::Test メンバ関数を呼びだしたのですが
どう書けばいいのでしょうか?
2重質問すいません
>>128 .* または ->* いずれかの演算子を使う。
>>127 普通の関数とクラスのメンバ関数ではポインタの型が違う。
ただの関数だとアドレスはひとつに決まるが、
クラスのメンバ関数だと
CGame dq;
CGame ff;
って二つあったとしたらどっちのTest関数やねんって感じ。
んで当然エラー。
>>128 んでC++ならあまりメンバ関数のポインタなんて使わない
そーゆーときは
interface ITest {
virtual void Test() = 0; //インタフェースの定義
};
class CGame : public ITest { //インタフェース継承して
virtual void Test(); //インタフェースの実装
};
vector<ITest*> g_InterfaceTable;
とでもする。
眠いのでもう寝るけど適当にググってHP探すか
いろいろC++の解説本でも読んでください。
132 :
124 :2005/08/20(土) 03:30:56
勉強不足ですね どうもありがとうございました。
名前空間の中にある変数はextern宣言できないんですか?
どうやって?
検索したらexternしなくても大域変数みたいでした
>>136 意味不明
ここは貴様のチラシの裏じゃない
宣言と定義の区別がついていないようだな
namespace ns { struct X {}; } のように構造体が宣言されているとき、あるブロックで using ns::X; と using 宣言するのと typedef ns::X X; のように型を定義するのでは何か違いがでるでしょうか?
typedefだとfriendの対象にならなかったような気がする。
>>139 理由は不明だが int X; って追加してコンパイルしてみると
using が通って typedef が通らない。
gcc 3.4.4 だと、順番で挙動が異なる。 MSVCだと、どっちでも通る。 // OK namespace ns { struct X; } using ns::X; int X; // NG namespace ns { struct X; } int X; using ns::X; だめだ。 using を使いこなす自信が無い。
コンパイラ依存だから使わないが吉
>>142 X hoge ;//<-型はどっちになるんだろう?
すまん、int Xか……。 ボケてた。
struct A { int i; A(int x) : i(x) {} A() {} }; struct B : public A { B(int x) : i(x) {} }; で、Bのi(x)でエラーが出るのはなぜですか? Aの i がそのままBに継承されると思ったのですが・・・・
>>147 それができるなら
B(int x) : A(0), i(x) {}
こんな場合に i の初期化が2通り存在してしまう。
>>148 14882:2003§12.6.2.2.当たりでしょうか。
If a mem-initializer-id is ambiguous because it designates both a direct non-virtual base
class and an inherited virtual base class, the mem-initializer is ill-formed.
言われてみれば確かにそうです。Bの初期化リスト中にAのコンストラクタを
呼び出すようにするのが正しいようです。曖昧さを持たせないようにします。
ありがとうございました。
150 :
デフォルトの名無しさん :2005/08/22(月) 03:58:14
JAVAをobjectorientまでやって今度はC++を学ぼうとしています。 JAVAはでっかいライブラリのページがあって googleで使いたいメソッドの名前を予想したりして 打ってメソッドからメソッドへ(またはクラス)リンクで飛べてすぐに探せたのですが、 C++では探すのに結構苦労しています。 普段どのように探してるのか教えてください。 compilerとしてvisual studioを使ってます。
今、ライブラリを作っているんだがコメントのつけ方で悩んでいる。 関数の詳しい説明を、 1) ヘッダファイルの関数宣言部分に書く 2) 関数の実装部に書く このどちらがいいんだろう? 例えばhoge()があった場合、 (hoge.h) // 1)の場合の例 /* hogeする関数。 [param] a : hogeのa用 */ void hoge( int a ); (hoge.cc) // 2)の場合の例 /* hogeする関数。 [param] a : hogeのa用 */ void hoge( int a ) { hogehoge(a); } ライブラリと言っても、ほとんど自分専用で変更も多いので .libファイルとかにまとめない予定。 おまいらならどうする?
>>153 ちゃんと整備する気があるなら、利用者にソースを公開しない可能性を考えてインクルードファイルに書くのがいいのでは?
で、できればDoxygenスタイルに統一するといいかも。
あくまでも自分専用だと言うなら、使い方まで書きゃしないだろうから実装に書いた方がいいかも知れないけど。
俺はヘッダーファイルを関数一覧表として見やすく保っておきたいから 実装部に書いてるな。 関数の使われかた(インタフェース)に関するコメントであって、実装 に関するコメントではないと考えるのならヘッダーファイルに書くのも一理あると思う。 どのみちDoxygenでドキュメントを生成するならどちらに書いても同じかもしれない。 ここ数年Doxygenというか、javadocスタイルでコメントを書いているけど 自分だけだったらソースを直接見た方が早いのであまりドキュメントを生成していなかったりする。 というか、コーディング規約スレか?
ドキュメント生成なら、NaturalDocs マジオススメ。
Doxygenよりもか?
NaturalDocs はコメントの形式がきれいなのですき。 // // Function: regex_replace // ------------------------------------- // 正規表現置換を行う。 // ------------------------------------- // Parameters: // rex - 正規表現パターン // src - 置換対象文字列 // rep - 置換文字列 // // Returns: // 置換された文字を返す。 // string regex_replace( regex const & rex, string const & src, string const & rep ) { ... } ソースだけ見ても分かりやすい。
見やすいかもしれんが 長い…
プログラマの皆さん 関数やクラスの名前、はたまたプロジェクトやソフトウェアのいろいろな名前、 名前は飾りですか? それとも、その機能(特徴)を的確に表し 短く覚えやすい名前をつけますか? いざ名前をつけるとなると、自分の場合悩んで決めあぐねて困っています 私はこう付ける等のアドバイスやヒントを教えてください。お願いします。
>>160 1行空け読みづらいな。しかも飾りですかって煽りですか
というかスレ違い
162 :
153 :2005/08/22(月) 23:11:50
トンクス。 NaturalDocsよさげだな。 JavaDocでドキュメントを作ったことがあるんだが、 コメント形式が好きじゃないんでコメントからドキュメント作成は諦めてた。 ドキュメントが作れるならどっちに書いてもいいと思うんで、 なるべくヘッダを見やすくしたい俺は実装部に書くことにしました。 >> 160 名前は長くてもわかりやすいのを付けるようにしている。 といってもまだ学生で、プロジェクトに参加したことがないので どんな形がいいのかよくわからないのですが。。。
>>160 関数やクラスはその機能にあった名前をつける(というか、それ以外どうしろと)
ソフトの名前は、趣味で勝手に汁
164 :
160 :2005/08/23(火) 00:24:25
>>161 煽りではないです 読みづらいのはすみません。
>>162 163
二人のレスをよく呼んで気づかされたんですが、 私が悩んでいたのは
関数やクラス名ではなくて、ソフト・プロジェクト名だったようです。
機能にあったわかりやすい名前を関数・クラスに付けるのは当たり前ですね。
さて、いよいよスレ違いくさくなってきたのでこれで最後のレスにします。
>>ソフトの名前は、趣味で勝手に汁
この言葉結構参考になりました。
禿同
operator=の実装などでオブジェクト自身の参照を返したい場合、戻り値は return *this; と書けば希望通りに動作してくれるのでしょうか? 自分で試したいけど、PCぶっ壊れて試せない(;´Д`)
OK
>>167 operator=の戻り値の型をきちんと参照型にしておけよ?
どうでもいいけど、何故そこに疑問符をつけるのだろう……
自分に自信が持てないから
OpenPNLコンパイルするだけで30分近くかかってるんですが そういうものなの? templateを多用されてるから?
>>172 Firbirdのコンパイル(gcc3.3のコンパイル含む)に12時間かかった漏れに喧嘩売ってますか( ^ω^)
PHPやApacheのコンパイルも1時間以上余裕でかかるorz
つミP54C-133
ペン4 2G とかでも30分かかります
>>172 ,173,174
マシン余ってるならdistccを使おう
>>175 稼働可能機がEPSON PC-286V-STDしか‥‥(;^ω^)
177 :
デフォルトの名無しさん :2005/08/25(木) 15:39:40
上手なincludeの仕方(モジュールの分け方?)みたいなのが解説されている サイトや書籍があったら教えて頂けないでしょうか。 172氏じゃないですが、どうもその辺が下手なせいで、コンパイル時間が長い気がしてなりません。 今のところ、ヘッダには、インラインを使う必要が無い限り、なるべく他のヘッダをincludeしないで 型宣言だけで済ます…くらいしか工夫をしていません(これ自体も良いのか悪いのか…)。
コンパイル時間を減らすためなんてアフォラシス
依存度を下げる事が再コンパイル時間を減らす事につながるので、 コンパイル時間を減らすことはオブジェクト指向言語として、 最大の目標といっていい。
>>179 やってはいるのですが、どうも…マシンが非力なせいもあるのですが
>>180 なるほど、コツとか近道は無くて、結局設計の腕を上げるしか無いと言うことですか
お二人ともありがとうございます
_, ._ ( ゚ Д゚) …
というか、ヘッダファイルという考え方自体が、古いんだけどな。 どうしてもコンパイルが遅くなる。 苦肉の策としてVCはプリコンパイル済みヘッダという仕組みで早くしているけどね。 D言語とかうらやましい。
かといって、#include がなくなると、 class bind_t { ... #define BIND_RETURN return #include "bind/bind_template.hpp" // <- スクリプトでつくった実装ファイル #undef BIND_RETURN }; のような事が出来なくなっちゃうので モジュール読み込み形式と、 テキスト展開方式の2パターンが欲しいところ。
BCB使ってるけどC++コードとPascalコードじゃコンパイル速度洒落にならないほど違うしなあorz
#nullpo
#include "Global.h" とかやってた事のある奴挙手
cout << hex << 100 << endl; ってやると16進数での100の表示が出ますが、 この結果をchar配列に詰めたいときはどうすればいいんでしょうか。 文法的には間違ってますが、 イメージとしては char[10] buf; buf << hex << 100; みたいな感じ。
char[]にこだわるなら処理系がstrstream使えるか調べろ。
sprintf(buf, "%X", 100);
194 :
190 :2005/08/26(金) 15:16:03
195 :
デフォルトの名無しさん :2005/08/26(金) 20:07:06
テンプレートクラス内で型定義して template <class T> class Hoge{ typedef vector<int> Array; //新しい型の定義 static Array staticData; //定義した型の静的メンバ変数を使う }; //cppファイルで静的メンバ変数の実体を template<class T> vector<int> Hoge<T>::staticData; ならOKですが template<class T> Hoge<T>::Array Hoge<T>::staticData; とやってもHoge<T>::Array型を作る事ができずエラーになってしまいます。 この場合の書式はどのようにすればいいのでしょうか? コンパイラはVC2003です。
>>195 template<class T>
typename Hoge<T>::Array Hoge<T>::staticData;
>>196 なるほど、typenameですか。
どうもありがとうございました。
hoge.hhに class hoge { private: static const string name[3]; }; とあって、hoge.cc内に const hoge::name[0] = "aho1"; const hoge::name[1] = "aho2"; const hoge::name[2] = "aho3"; とやると error: conflicting types for `const std::string hoge::name[1] と怒られます。 member内のstatic constに配列は扱えないのですか?
199 :
198 :2005/08/26(金) 21:09:18
const hoge::name[3] = {"aho1", "aho2", "aho3"}; で出来ました。スレ汚しスマソ。
200 :
デフォルトの名無しさん :2005/08/26(金) 21:55:56
クラステンプレートの中にメンバテンプレートを持たせたとき、 メンバの宣言と定義をわけて書く場合は、下のような感じでいいんでしょうか。 (これが一般的でしょうか、という意味です。試行錯誤でコンパイルが通るようになった結果がこれです) template <class T> class A{ public: A(T t){ } template <class S> void f(S s); }; template <class T> template <class S> void A<T>::f(S s) { } 「template <class T>」「template <class S>」の位置はこれでいいのかな、と。 たとえば「const C&」と「C const&」が同じ意味を持つように、上の例でも 他の書き方があったりしますか?
>>197 なぜ typename が必要かわかってるのかなあ?
>>200 template<typename T> template<typename S> void A<T>::f(S s)
って、およびでない?
202 :
200 :2005/08/26(金) 23:12:41
>>201 (・∀・;)あぁ、それも他の書き方ですね。
キーワードの順序的にはこれしかない(これが普通)ってことですか。
Fedora Core 2でUSB<->Serial変換を使って制御をやっています。 自前のclassですが、基本はC標準のread()とwrite()を使ってのやり取りです。 Win 2kのハイパーターミナルで通信するのに比べると、 FC2でreadする動作速度が遅いようです。 何かreadを高速化させる方法と言うのがあるんでしょうか? タイミングの問題でしょうか。
205 :
203 :2005/08/27(土) 22:29:11
1つ以上の要素を持つ STL コンテナから end() で反復子を取得し、それをデクリメント した場合、その反復子はコンテナの最後の要素を示すようになるのでしょうか?
>>206 そのコンテナのイテレータが ForwardIterator なら、大丈夫。
標準コンテナならすべて大丈夫。
>>207 さんありがとうございます。
ということは std::list のようなノード型コンテナはダミーのノードを内部に持っているのでしょうか?
もしくは反復子の内部にノードのポインタ以外の情報も持っているのでしょうか?
>>208 std::list なら実装がヘッダファイルに書いてあるはずだから、それを見るといいよ。
exportが使えるようになるのはいつだろう…
>>207 Bidirectional iteratorsの間違い?
212 :
207 :2005/08/28(日) 01:53:31
>>211 あ、そうか。 ForwardIterator だけじゃデクリメントが無いな。間違い。
質問させてください。 以下のようなプログラムを作り、g++でコンパイルして動作確認をしました。 //////// ここから//////// #include <iostream> class Test { public: void print(char *msg) { std::cout << msg << std::endl; } }; int main() { Test t1; t1.print("First print()"); Test().print("Second print()"); (new Test)->print("Third print()"); return 0; } //////// ここまで //////// 質問内容は次のレスに続きます。
続かねーよバーカ。
216 :
214 :2005/08/28(日) 16:44:20
main関数内1行目は普通に宣言してメソッドを使っているので うまく動いて当然であり、なんら疑問はありません。 main関数内3行目は、 Test *pt = new Test; という記述が使えることと、operator newがポインタを返すことから (new Test)が新しいTestオブジェクトへのポインタであると予想して 記述しました。結果は予想どうりうまく動きましたが、本当に この予想はあっているのでしょうか? 一番の疑問点はmain関数内2行目で コンストラクタは返り値が無いはずなのにTest()があたかも オブジェクトそのものである様に働いている点です。 いったいこれはどういう理屈なのでしょうか? 本屋で立ち読みして答えを探そうとしたのですが、 キーワードが分からずどこを探せばよいのか分かりませんでした。 もしよろしければ、何か手掛かりになるものを教えてもらえないでしょうか?
>>216 new Test については、予想も何も「新しいTestオブジェクトへのポインタ」を返すのが new の仕様。
予想はあっているが、予想して使うものではない。
あと、一般的には new で得たポインタは後で delete できるように扱うべき。
Test() は Test 型のテンポラリオブジェクト(一時オブジェクト)を作る式。
つまり Test() はオブジェクトそのものとみなせる。
>>216 そのTest()はコンストラクタじゃなくて一時オブジェクト。
2分もたってかぶってたスマソ
>>216 >結果は予想どうりうまく動きましたが、本当に
>この予想はあっているのでしょうか?
合ってる。
>一番の疑問点はmain関数内2行目で
>コンストラクタは返り値が無いはずなのにTest()があたかも
>オブジェクトそのものである様に働いている点です。
>いったいこれはどういう理屈なのでしょうか?
Test()は一時オブジェクトの明示的生成。
Test().print("Second print()")
という式全体の評価が終わったあと自動的に解体される。
221 :
220 :2005/08/28(日) 17:06:10
うおw 俺もスマソ
一時オブジェクトってスタックに取られるんだろうなやっぱ。 でかいオブジェクトを一時オブジェクトで作ると、スタックいっぱい消費する?
>>222 スタックに配置される処理系なら、そうなる
(そうでない処理系は使ったことないが)
224 :
214 :2005/08/28(日) 18:15:46
>>217 ,218,220
みなさん解説有難うございます。
つまり、例えば
Test t = Test();
これだと、一時オブジェクトを引数としてコピーコンストラクタが
呼ばれるということですね?
ところで、今回の「一時オブジェクト」はどの程度のレベルの本になら
書いてあるのでしょうか?中~上級ぐらいの本でしょうか?
225 :
デフォルトの名無しさん :2005/08/28(日) 18:20:30
もうちょっとマシな聞き方はできないのか? プログラミング言語C++でも読んどけ。
入門書にはあんまり載ってないかもね。 STL本だと結構使うから、さらっと説明される。
228 :
214 :2005/08/28(日) 21:15:30
>>225 ,227
そのあたりの本を見てみます。
有難うございました。
勉強のために、他人が書いた上手いコードを探しています。 感動したPDSやソースコードを紹介していただけますか?
Loki
Lokiもう一票 これ読んだ前後でC++観が変わった
>>230 , 231, 232
どうもありがとうございます。
コツコツみていきます。
文字をURLエンコードするにはどうすればいいのでしょうか。
void urlencode(char moji, char kekka[3]) { sprintf("%%%02X", (unsigned char)moji); }
↑ごめん、kekka[4]の間違い
>>236 kekkaを使ってないし、sprintfの引数おかしいし。
void urlencode(unsigned char moji, char kekka[3]) { sprintf(kekka, "%%%02X", moji); }
結果が返らんだろそれは。
え
結果は引き数経由で渡すから使い勝手は悪いな。
std::string urlencode(char moji) { std::ostringstream oss; if (moji == ' ') oss << '+'; else oss << '%' << hex << setw(2) << static_cast<int>(moji); return oss.str(); } こんなのとか(動作確認なし)
文字列対応 std::string urlEncode1(const char * str) { std::ostringstream oss; while (str[0] != '\0') { if (str[0] == ' ') { oss << '+'; } else { oss << '%' << std::hex << std::setw(2) << static_cast<int>(str[0]); } ++str; } return oss.str(); } std::string urlEncode2(const char * str) { std::string rtn; while (str[0] != '\0') { if (str[0] == ' ') { rtn += '+'; } else { char tmp[4]; sprintf(tmp, "%%%02x", str[0]); rtn += tmp; } ++str; } return rtn; }
グローバルに struct Map { int x; int y; //などなど }; Map g_Map[4096*4096]; //もっと広いかもしれない とかいう馬鹿でかいデータの確保に挑戦して失敗した場合 例外をキャッチするのは無理なのでしょうか? どこかの関数内で動的に確保したほうがいいのかな。
>>244 そこは一般にヒープではないし、起動に失敗するだけで例外は飛ばないかと
でも大抵のコンパイラでデフォルト設定だとスタックオーバーフロー起こしそうだな‥‥
247 :
244 :2005/08/29(月) 18:27:34
やばそうなので関数内で確保するようにしておきます。
グローバル変数でいくらでかい変数とってもスタックオーバーフローにはならんだろ。
>>247 関数内でとるのもいいけど、あんまりでかいデータを自動変数にすると、
スタックオーバーフロー起こす可能性があるから、ヒープに領域確保しておけ。
std::vector<Map> map( 4096 * 4096 ); みたいに。
>>249 おとなしくvectorにしておきます。
ところで馬鹿でかい領域でもvectorのメモリアドレス連続性は保障されているのでしょうか?
std::vector<Map> map( 4096 * 4096 );
memset( &map[0], 0, sizeof(Map) * map.size() );
とやっても大丈夫でしょうか?
>>250 一応現在は保障されているが
Mapがclassでデフォルトコンストラクタが定義されているなら
vector<Map>の構築時に全要素分呼ばれるので
Mapのコンストラクタでゼロ初期化するようにしとけばいい
>>250 Mapがゼロクリアを保証できるならいいが、そうでないならstd::fill()を使うのが無難。
C++はゼロクリアすると危険な場合があるので (自分または継承元が仮想関数を持つなどでRTTI情報、vTblを持つ場合、 及びそういうオブジェクトをメンバとして一つでも持つ場合) Mapがそれに該当するならmemsetだろうとfillだろうと危険ですな
254 :
250 :2005/08/29(月) 19:40:20
>>251-253 とにかくセル数が多くvTblのバイト分も馬鹿にならないので
継承や仮想関数は禁止でやってますが、
おとなしくコンストラクタで0クリアしておきます。
どうもありがとうございました。
>>251 vector<T> a(n);は、T()で一時オブジェクトを作って
それを全要素分コピーコンストラクタで塗るので
通常のコンストラクタが全要素数分呼ばれるわけではないな
mallocやnew char[]でいいやん
>256 それは悪い意味でのCの慣習だ
Win32のメモリ領域確保系関数って一回も使った事ないな スレ違いですねすいません
スレ違いが続くが。 コンストラクタでHeapCreateしてデストラクタでHeapDestroyするAllocatorを作ってみようかなと思案している。
>コンストラクタでHeapCreateして うわ! >デストラクタでHeapDestroyするAllocator うわわわわ!!
262 :
259 :2005/08/29(月) 23:03:06
260じゃないけどそんなバカ正直なアロケータ書いても糞重いだけだと思う
>>262 標準のコンテナに渡す場合、 non-static データメンバを持つ allocator は使えない。
>>264 そうですか。
ではHeapCreate~HeapDestroyはシングルトンにすることにします。
266 :
デフォルトの名無しさん :2005/08/30(火) 13:24:35
typedef CTypedPtrArray<CObArray,CNode*> NodeArray; class CNode { public : NodeArray* GetChileNode(); } このように書くと、「1行目でCNodeが見つからないよ」とコンパイラにはじかれてしまします。 CNode内のメソッドでNodeArray型を使用したいので、CNodeの前にNodeArrayを宣言したい。 しかし、CNodeの前にはNodeArrayが宣言できない。 という状態なのですが、どのようにすればこの状態を解決できるでしょうか? アドバイスよろしくお願いいたします。
class CNode; とだけ宣言したらどうだろう。
268 :
デフォルトの名無しさん :2005/08/30(火) 13:34:07
>>267 ありがとうございます。
先頭行に、「class CNode;」の宣言を入れたら、コンパイルが通りました。
クラス宣言を2回以上しても大丈夫な事を知りませんでした。
勉強になりました。
>>268 一応
クラス宣言
class Hoge;
クラス定義
class Hoge { ... };
宣言と定義は違うってことで
>>269 なるほど。
そういう扱いになる訳ですね。
ありがとうございました。
>>271 定義は宣言を含むってのは
関数定義がプロトタイプ宣言を含むのと同じだね
質問です。 struct X {}; typedef X * Handle; typedef const Handle HandleA; typedef Handle const HandleB; 上記定義において、 HandleA と HandleB の型が同一であることは規格で保障されていますか?
>>273 もちろん。
そこで並べる順番は関係ない。
275 :
273 :2005/08/30(火) 18:35:28
>>274 ありがとうございます。
const Handle が、const X * に、
Handle const が、 X * const にそれぞれ展開されるんじゃないかと
悩んでいたのですっきりしました。
276 :
デフォルトの名無しさん :2005/08/30(火) 21:02:21
メンバ関数ポインタを介して、基底クラスの関数を呼び出したいのですが どうやっても上手くいきません。仮想関数では無理なのでしょうか。VC6使ってます。 #include <iostream> using namespace std; class Base { public: virtual void Foo() { cout << "Base::Foo" << endl; }; }; class Bar : public Base { public: virtual void Foo() { cout << "Bar::Foo" << endl; }; }; int main() { Bar *pBar = new Bar; void (Base::*pFoo)() = pBar->Base::Foo; (pBar->*pFoo)(); // pBar->Base::Foo() delete pBar; return 0; }
>>276 おまいは、メンバ関数ポインタの定義の仕方をちゃんと調べたのかと(r
278 :
276 :2005/08/30(火) 21:34:21
>>277 戻り値の型 (クラス名::*)(引数リスト)
こう解釈してますが…何か違うのでしょうか?
>>278 初期化子が変
それから、仮想関数へのポインタはvtblの先頭からのオフセット
282 :
276 :2005/08/30(火) 21:57:57
void (Base::*pBaseFoo)() = Base::Foo; (pBar->*pBaseFoo)(); void (Bar::*pBarFoo)() = Bar::Foo; (pBar->*pBarFoo)(); デバッガで追ってみましたがどちらも最終的にBar::Fooに。 Baseにキャストしても元がBarなんで、結局Bar::Foo やっぱり無理なんですかねぇ...
>>276 void (Base::*pFoo)() = &Base::Foo;じゃないとコンパイルが通らないと思うが。
そうしてメンバへのポインタを使ったところであれだ。自分で試してみろ。
>>282 そりゃそうだ。じゃなきゃ仮想関数の意味がない。
アップキャストしたらできないか?
286 :
276 :2005/08/30(火) 22:17:32
pBar->Base::Foo(); ↑のように直接記述したり、virtual外せば問題ないのにな。 融通きかないみたいなんで別の方法考えます。 お騒がせしました。
>>286 メンバへのポインタで仮想関数が適切に呼ばれないほうがよっぽど融通きいていないだろ。
派生クラスが意図的に基底クラスのメソッド呼び出さないようにとかしてたら偉いことが起きそうだな‥
明示的になら呼び出せても良さそうな気はするが。
いや、明示的には呼び出せるけどその記述の仕方が気に入らないらしい
292 :
デフォルトの名無しさん :2005/08/31(水) 11:41:14
C++の例外処理機構って、ifとgotoでやれることのシンタックスシュガーみたいなもん? もちろん関数を越えてジャンプできるのは凄いけど。
>>292 そのとおりだけど、それを言うとあらゆる制御構造がifとgotoのシンタックスシュガーだな。
294 :
デフォルトの名無しさん :2005/08/31(水) 11:48:00
>>293 でも他の制御構造は一応条件を判断する要素は残ってるでしょ?
C++の例外処理機構はそういうのすら画しちゃってるから。
>>294 言いたいことがよくわからない。
例外処理の場合はソース中には分岐の条件が明示されないけど、
実際には分岐が行われる。
>>295 例外 or setjmp/longjmpそれ自体は分岐じゃねーだろ。アフォ?
まともに学ぶ気がない奴が言い訳を探してるだけだろ。
298 :
デフォルトの名無しさん :2005/08/31(水) 12:53:10
話がかみ合わないスレはここですか?
>>296 どのcatchに捕捉されるかの分岐があるだろ。
>>292 更に遡るときローカル変数のデストラクタを呼んでいくのを忘れるな。
301 :
デフォルトの名無しさん :2005/09/01(木) 04:15:26
例外処理とstack unwindingは切っても切れない関係にあると思うけど
303 :
デフォルトの名無しさん :2005/09/01(木) 16:44:30
{}ブロックから抜けるときにスコープの変数解放するってだけの話じゃん。例外とか関係ないし。
>>303 はあ、それをするのが例外処理の重点のひとつじゃないか
何言ってんの
305 :
デフォルトの名無しさん :2005/09/01(木) 17:16:25
ifだろうがgotoだろうがthrowだろうがブロック抜けるときにやる処理は変わらねーんだよ 例外処理機構だけが特別になにかするわけじゃないっ話だよ 筋読め
つかシンタックスシュガーであるか無いかからどんな価値のある結論が出るというのか
Stack unwinding (wikiの定義) 関数がreturnするときのスタックの調整 (大昔からの用語だと思われる) stack unwinding (C++の定義) tryからcatchに移るときにデストラクタが自動で呼ばれるプロセス (標準文書で、例外が"return"中のときのいろんな制限の説明のために 用意された用語。7ヶ所出てくる) wikiの定義で語っている多くの本が間違っていると思われる。 wikiの定義で語るならreturnの説明のときにするべきだから。
なんか、言語の機能としての「例外処理」と、広義の「例外処理」とがごっちゃになっているなあ 言語の「例外処理」機能が話の主題のはずだか、 スタックの巻き戻しが無関係とかいってる奴はそこいら変を勘違いしてる
>C++の例外処理機構って、ifとgotoでやれることのシンタックスシュガーみたいなもん? setjmpとlongjmpのようなものだよ派 | +- stack unwinding について触れる派 | +- 掲示板で難しい話はしない派 catch節にgotoでジャンプするようなものだよ派 | +- 関数を越えてジャンプできるのは凄いよ派 | +- if や goto と全く同じだよ派
310 :
デフォルトの名無しさん :2005/09/01(木) 19:58:55
>なんか、言語の機能としての「例外処理」と、広義の「例外処理」とがごっちゃになっているなあ 誰もそこはごっちゃにしてないと思うが
一連の流れを読んでいて、「C#で実現してることなんて全部 Cでできることばっかりじゃないか、たいしたことないね」、 と言って何も学ぼうとしない前職の上司(44歳、Cとawkしか 使えないので役に立たない)を思い出した。
>>310 じゃあ、何で例外処理機能の話をしてるのに、「stack unwinding は関係ない」という話が出てくるんだ?
勘違いしてるとしか思えん
すべての言語はチューリング等価だよ。
そもそもシンタックスシュガーって何よ。
>>305 setjump~longjumpでデストラクタが呼ばれないのはどうお考えで?
つか
>>315 の説明から判断すると高級言語全体がそもそもシンタックスシュガーだろ。
重箱の隅つついてどうでもいい話引き伸ばすなっての
>高級言語全体がそもそもシンタックスシュガーだろ これが元の話と何の関係もないのは言うまでも無いが、どうでもいい話というのは同意
例外機構はifとgoto、それからグローバル変数とか戻り値とかを使えば
「ほとんど同じ」ことは出来るので、シンタックスシュガーと言えるかもね。だから何
>>292 となると次に興味が沸くのはなぜC++には例外が導入されたか、
どのように使い分けるのが良いか、といったところかな。
320 :
デフォルトの名無しさん :2005/09/02(金) 15:31:21
例外といえば、前から気になっていたことがあるので質問します。 access_violation break_point derived_by_zero page_error stack_overflow の各種例外を定義するとき、 それぞれどの標準例外クラスから派生するのが妥当でしょうか? stack_overflow は std::overflow_error、 derived_by_zero は logic_error かなと考えていますが。 皆さんの意見を聞かせてください。
runtime_error
exception
null_pointer
324 :
320 :2005/09/02(金) 19:01:57
derived_by_zero ってなんだ。素で間違えた
正しくは divide_by_zero です。
access_violation は runtime_error
break_point は domain_error
divide_by_zero は logic_error
page_error は runtime_error
stack_overflow は domain_error
今のところ、上記のような感じで考えてますけど、
厳密に区分けするのは面倒なので、
>>322 さんの言うとおり
全部 exception から派生させるのもひとつの手かも。
>>324 OSかエミュレータでも作ってるん?
stack_overflowはruntime_errorっぽい気はするが
C++でコンストラクタから別のコンストラクタを呼ぶにはどうすればいいですか? class Test { private: int value_; public; Test() { //Javaだとここにthis(150)と書けば↓のコンストラクタが呼べる } Test(int value) : value_(value) { } }
別のコンスラクタは呼べない。
328 :
326 :2005/09/03(土) 13:50:58
ガーン… ということは Test(int a, double b, std::string c, T d, … U w) : a(a), … w(w) { //長ったらしいいろんな初期化処理(数十行) } というコンストラクタがあって Test(int a, double b, std::string c, T d, … U w, V x) というコンストラクタを作りたくなったら 処理は全部コピペするしかないということですね… やっぱC++は設計が古いんだな…
>>326 C++オブジェクトモデルでは、オブジェクトのライフタイムが
コンストラクタが完了した時点で始まると定義されている。
コンストラクタからコンストラクタが呼び出せるとすると、
オブジェクトのライフタイムが定まらない。
例えば this(150) のあと、 Test() の続きで例外がスローされた場合に
デストラクタが実行されるかどうかが定まらなくなる。
プライベートメンバ関数に初期化処理を分離すりゃええやん
*this = Test(150);
非コンストラクタなメンバ関数だとメンバ変数の初期化できないけどな。
>>330 ,333
代入と初期化の違いはわかってて言ってるのか?
どうしても初期化が必要ならポインタで管理すればいいんじゃ そのあたりは設計の妥協点
コピペするくらいだったらマクロ使えばいいじゃん。
>>326 それができるんだったら、そもそもメンバ初期化リストの意味がないんじゃない?
: value_(value) は value_ = value; とは違う。
初期化はそのオブジェクトの一番最初の構築を意味するわけで、
コンストラクタからコンストラクタを呼べたら二回メンバ変数を初期化する事になってしまう。
そもそもJavaでは : value_(value) とは書けないので、その例でJavaでは呼べると言っても意味がないと思うけど。
コンストラクタの持つ意味自体がC++とJavaでは少し違っているんじゃないのかなぁ。
いつメンバが初期化(最初の構築)されるのかとか。
Javaはメンバとなるオブジェクトを基本型以外は参照型で持つし、
C++ほど定数性にこだわっていないから、その辺の違いから来ているのかもね。
>>328 そのクラスをインターフェイス・クラスと内部実装クラスに分離して、インターフェイスが内部実装を非公開継承もしくはメンバとして持つという手段もある。
インターフェイスの各コンストラクタで共通する部分を内部実装のコンストラクタに落とし込むわけだ。
これだからJava厨は。
何!さっきからどうもJava臭いと思っていたらやっぱりそうか。
総合的に言って、Javaのほうが優れているというのは常識なのでしょうか?
>>341 評価基準による。自分に合った評価基準で言語は選ぶものだ。
っていうか総合的って何だ。っていうか釣りだろ。
つーか釣られんな
つーかJavaに限らずD言語とかでもthis()できるよ
345 :
C初心者です :2005/09/03(土) 21:18:09
質問です。 NT系のOSってノートパッドに書き込める容量は制限されて無いみたいなんですけど、 Meってノートパッドに書き込みすぎるとメモリ不足って言う表示がでてしまい、それ以上書けなくなってしまいます。 そこで、Meで動作する容量の制限されないノートパッドをC言語で作ってるんですけど、イマイチ作れません。 だれか作り方教えてください。お願いします。
>>345 ここもスレ違い。タイトルを読むってことはできないのか?
まず根本的にだ。 おまいがやりたいのはCでメモ帳もどきを作ることなのか、 容量制限のないメモ帳を使いたいのかということ。 前者なら自分で勉強しろとしか言えん。つかその程度のことを調べられないのなら 根本的にプログラミングは向いていない。 Win32APIとか、Windowsプログラミングでググればいくらでも参考になるページは出てくるから。 後者なら、んなものいちいち自作しないで既存のエディタ使え。 秀丸でもEmEditorでもxyzzyでもTeraPadでも、メモ帳とは比較にならない レベルのエディタが腐るほどあるから。
348 :
C初心者です :2005/09/03(土) 21:28:03
>>347 そうですか。回答ありがとうございます。
ちなみに、容量制限のないメモ帳をVCなど使わないで作りたかっただけです。
VCなど使わないで作りたかったとは、BCCを使っているとか、GCCでやっているとかか?
CよりC++やC#やJavaやHSPを使った方がいいんジャマイカ
HSPてなに?
Hなスピード
C++やC#やJavaと同列に置くのが解せん
355 :
C初心者です :2005/09/04(日) 12:08:12
レス遅れてスイマセン。
>>349 もうちょっとソース組み立ててから相談します。
>>350 BCCでコマンドプロントを使ってコンパイルしてます。
>>351 説明間違えてました、C++で作ってます。
それだけじゃまだOOPLになってない
>>356 って、昔は構造体も関数もなかったのかよ!
よくそんなもんを使おうと思う人間がいたものだ。
タダで楽ですから。この二つの単語に人間は惹きつけられる
360 :
デフォルトの名無しさん :2005/09/04(日) 20:05:44
弟子食いの古賀先生w
361 :
デフォルトの名無しさん :2005/09/04(日) 22:44:38
こんばんわ、質問があります。 環境C++6.0 windowsxp 今、ハードディスクやCDの容量を調べるプログラムを組んでいます。 GetDiskFreeSpaceExをつかって、ハードディスクの使用量と空き容量は入手できたのですが、 焼かれたCDの空き容量が0になってしまうのです。マイコンピュータのCDドライブのところから、 プロパティを開くと空き容量が表示されるのですが、プログラムでそれを入手することが出来ないのです。 基本的な質問ですが、知恵をお貸し願えませんでしょうか? よろしくお願いします。
363 :
デフォルトの名無しさん :2005/09/04(日) 23:05:51
ありがとうございます >>362
たとえば以下のようなセルからなるマップというクラスがあるとして class Map { struct Cell { }; friend class Cell; int WorldWidth; //世界の大きさなどはMapクラスが管理 int WorldHeight; Cell* pCell; //格CellへのアクセスをMapクラスが抽象化する。 }; ここでCellクラス内のメンバ関数が親のMapクラスの情報が欲しいとなれば void Hoge(Map* pMap) { pMap->WorldWidth; } と、関数の引数にもらってthisポインタのように使う以外に何かいい方法ありますか? MapクラスへのポインタをCellクラスのメンバ変数に持たせるのはメモリの無駄遣いだと思うし、 静的メンバ変数などにすると複数のMap、(裏の世界とか、夢の世界とか)に対応できないような気もします。 関数の引数でアクセスするのが一番素直なようにも思うんですが、 Cellのメンバ変数が再帰しまくったときにスタックに積みまくるのもなんか無駄なような気がしてます。 なんかこう書くとエレガントだとか、効率的だとかあればご教授お願いします。
>>364 訂正
>Cellのメンバ変数が再帰しまくったときに
Cellのメンバ関数が再帰・・・
です。
>>364 CellがMapを関知しちゃイカンだろ
CellにはMap側で計算済みの値を渡すべき
>>364 基本的に
>>366 の言うとおりだし、
そもそもスタックが気になるほど再帰しまくるならデータ構造から見直すべき。
しっかりした構造なら大抵は再帰の深さなんてせいぜいlog(セルの個数)程度のオーダーだと思われ。
それを超えるなら簡単に再帰を使うべきではない。
つまり引数にすること自体は問題なし。
368 :
デフォルトの名無しさん :2005/09/05(月) 17:23:26
VC7.1+STLPortなんですが、 stringstreamのポインタ操作が機能しません。 具体的には下記のコードでp0とp1が共に0を返し seekpが機能しません。 結果"abcdefgh"と出力されます。 strstreamの場合正常に機能します。 なぜでしょうか? std::stringstream stream( std::ios::out ); const std::ios::pos_type p0 = stream.tellp(); stream << "abcde"; const std::ios::pos_type p1 = stream.tellp(); stream.seekp( -3, std::ios::cur ); stream << "fgh" << std::endl;
369 :
320 :2005/09/05(月) 18:19:26
>>325 非常に遅くなりましたけど、
Win32 の構造化例外を、C++ の例外に変換する際のはなしです。
普通は華麗にスルーするところですが、どうしても捕捉しておく必要があったので。
>>368 STLPortのバグ
VC6.0ならともかくVC7.1なら付属のほう(dinkumware)がむしろ安定してるからそっち推奨
>>370 嘘つくなタコ。std::ios::outを指定すると、:ostream iteratorが
指定されるだろ。これはramdom access iteratorではないので、
シークができないし、現在位置も知る事ができない。
従って、tellp()をすると、std::string::nposが返る。
正しく動かすには、std::stringstream stream( std::ios::out | std::ios::in );
としないとだめ。
むしろ、このまま正しく動くような動作をするdinkumwareの方が糞だろ。
少なくとも俺の環境でVC7.1+STLport4.6.2では、上のようにフラグを指定
すれば正しく動作する。
あ、失礼 ×std::string::npos ○std::ios::pos_type(-1)
373 :
370 :2005/09/05(月) 22:11:07
すまん。質問のios::outの指定を完全に見逃してた。 370は撤回させてくれ。371のとおり。
374 :
368 :2005/09/05(月) 22:40:58
ポインタの参照先に実体があるかどうかを調べる関数はありますか?
376 :
デフォルトの名無しさん :2005/09/06(火) 00:03:07
ない。
サンクス
コレじゃ無理かな。 今環境無いから試せないけど。VC++限定で template< typename T > bool is_valid_pointer( T const volatile * p ) { __try{ (void)(*p); } __except( EXCEPTION_EXECUTE_HANDLER ) { return false; } return true; }
自分で管理するという方法もある。 俺ならスマートポインタを素直に使ってそんな状況そのものを発生させないが #include<set> template<typename T> struct valid{ static std::set<const valid*>check; valid(){check.insert(this);} ~valid(){check.erase(this);} static bool isValid(const T*p){return check.count(p)!=0;} }; template<typename T> std::set<const valid<T>*> valid<T>::check; こんな風に定義して //有効か確認機能付の構造体 struct X:valid<X>{}; X::isValid(p);//pが有効か確認
380 :
デフォルトの名無しさん :2005/09/06(火) 00:41:02
xをy(≠整数)乗するにはどうしたらいいのでしょうか?
パワー、パワー
#include <math.h> #include <stdio.h> void main( void ) { double x = 2.0, y = 3.0, z; z = pow( x, y ); printf( "%.1f to the power of %.1f is %.1f\n", x, y, z ); }
383 :
デフォルトの名無しさん :2005/09/06(火) 00:59:34
384 :
364 :2005/09/06(火) 02:12:33
>>366 さんの
おっしゃるとおりだと思いますが、
元々の形はすべてのCellで共通のデータをstaticとして持つでした。
しかしstaticで持ってしまうと、複数のマップ対応に拡張できない。
ということで364の形式、MapクラスはCellクラスからなる、
Cellの共有データはMapクラスが管理ということで
Map Omote_no_sekai;
Map Ura_no_sekai;
というように書けるようにしてみました。
今のところCellがMapを関知することのデメリットはよく分かりません。
静的メンバ変数に比べると関数引数で受け取る必要があるので面倒ですが・・・。
>>367 確かにlogのオーダーなので、それほど問題ないようならこのままいってみます。
蛇足になりますが、静的メンバ変数をあるグループごとに複製したい場合
テンプレートのを使うのは邪道でしょうか?
つまり
template<int WorldSize, int MapType>
class Cell
{
static int arekore;
};
として
Cell<256, 0> Omoteno_sekai[256*256];
Cell<256, 1> Urano_sekai[128*128];
Cell<128, 2> Yume_no_sekai[128*128];
としてしまう手です・・・。
>>371 ,373
> std::ios::outを指定すると、:ostream iteratorが指定される
これ、何の話?さっぱりわからない。
「:ostream iterator」って何?
何に「:ostream iterator」が指定されるの?
> std::stringstream stream( std::ios::out | std::ios::in );
これはつまり std::stringstream stream こうしとけばいいってことだな。
>蛇足になりますが、静的メンバ変数をあるグループごとに複製したい場合 テンプレートのを使うのは邪道でしょうか? その方法はあまりいいものとはいえない。 Cellをテンプレートにすると、当然それを含むMapもテンプレートにしなければならなくなる。 すると、そのMap、Cellを引数にするような関数もテンプレートにせねばならない、などと 際限がなくなってしまう。 struct MapInfo{ int nWorldHeight; int nWorldWidth; }; struct Cell l void Hoge(const MapInfo* p) {....} .}; class Map { MapInfo m_mapInfo; Cell* m_pCellArray;//Cellのコレクションをメンバに持つ。 }; ・CellをMapの外に出す。 ・friend class はできるだけ使わない。 って感じで、テンプレートを使わない場合はできるだけMapとCellとの癒着をなくす方がいい。
>>371 自分もちょっとわかりません。
それはC++の仕様なのでしょうか?
それともSTLPortの仕様なのですか?
STLPortのソースを追ってみると
STLPortのstringstreamは、内部にstringとは別の小さいバッファを持っていて
何らかの条件でバッファの中身をstringにフラッシュするみたいです。
tellpが返すポインタはその小さいバッファのものである為
いままで書き込んだ文字列を考慮した位置を返してくれる訳ではないみたいです。
>>385 先頭の ':' は明らかに typo だろ。
>これはつまり std::stringstream stream こうしとけばいいってことだな。
その通り。それがデフォルト・パラメータになっている。わざわざ std::ios::inを
外したオープンフラグを指定したものだから、std::ostringstreamと同じに
なってしまった。それだけの話だ。
>>387 反復子(iterator)について勉強し直せ。自然と理解できる。
>>389 basic_ostringstreamはbasic_ostreamの派生クラスですよね?
そのbasic_ostreamのメンバであるtellpが
basic_istreamを派生することによって使えるようになるなんて
なんか解せないんですが、それが正しい動作なんですか?
いろいろ調べてみましたが basic_ostringstreamがbasic_ostreamのメンバアクセスに制限があるという 資料は見つけられませんでした。 basic_stringのiteratorはランダムアクセスイテレータですから 実装不可能だとも思えません。 やっぱりSTLPortのせいだと思うんですが・・
>>390 それは勘違い。std::basic_ostreamの反復子は出力反復子(ostream iterator)のため、
tellp()、seekp()メンバ関数の意味を正しくインプリメントできないのだ。
同様にして、std::basic_istreamの反復子は入力反復子(input iterator)のため、
tellg()、seekg()メンバ関数の意味を正しくインプリメントできない。
tellp()、tellg()、seekp()、seekg()は、前方反復子(forward iterator)でのみ、正しい
本来の意味のある値を返す。この前方反復子を備えているクラスは、std::basic_fstreamと
std::basic_stringstreamだけだ。
>>371 の、random access iteratorというのは間違い。そこまで厳しい要件を必要と
しない。しかし、おっしゃる通り、std::basic_ostreamとstd::basic_istreamを継承した
クラスでないと、tellp()~seekg()メンバ関数が使えない。従ってstd::vectorのような
ストリームを継承したのではないくコンテナは、それらの特別なメンバ関数がない。
当然std::listのような双方向反復子(bidirectional iterator)を備えたクラスでも、
seek?()、tell?()が使えない。
あーでもこの時間だしな・・・・誰かISO/IEC調べてもらえませんか?俺はもう 寝なければならないので。
>>388 typo だとは思うが、あまりにも脈略が無いんで何を打とうとしたのか想像できない。
std::ostringstream と同じになったと言われても、 std::ostringstream の
tellp() が 0 を返す理由になるとは思わない。
(>371,372 が正しければ -1 が返るらしいが、 >368 では 0 が返ると言われている)
>>389 うーん。 iterator はよく知っているつもりだけど、 >371 の意味は理解できない。
>>392 「std::basic_ostream の反復子」の時点で意味不明なわけだが。
std::basic_ostream::iterator のようなメンバは存在しない。
>>393 今までは何を根拠に言ってたんだ?
cygwin g++ 3.4.4 で試してみた。 以下のコードで 'abfgh' が出力された。 やっぱ STLport のバグじゃないの? >370,373 は、なんで >371 で納得したんだろう? #include <sstream> #include <iostream> int main() { std::stringstream stream( std::ios::out ); const std::ios::pos_type p0 = stream.tellp(); stream << "abcde"; const std::ios::pos_type p1 = stream.tellp(); stream.seekp( -3, std::ios::cur ); stream << "fgh" << std::endl; std::cout << stream.str() << std::endl; return 0; };
396 :
デフォルトの名無しさん :2005/09/06(火) 09:04:37
iostreamはアイオーストリーム じゃあ、curses ってなんて読むの
398 :
デフォルトの名無しさん :2005/09/06(火) 10:08:34
397>> 辞書に載ってないから聞いたんだ~!! ちなみに、cygwin も皆さんは何て読んでいるのですか?
400 :
デフォルトの名無しさん :2005/09/06(火) 11:25:26
basic_ostream の tellp の説明を読むと、以下のように書いてある。
> basic_iosのメンバ関数 fail()がtrueを返すと、tellp() は、
> pos_type(off_type(-1))を返して失敗を伝えます。
> それ以外の場合は、rdbuf()-> pubseekoff(0,cur, out)を呼び出して、
> 出力シーケンスのカレントの位置を返します。
よって tellp の実装は、streambuf の実装に依存する。
basic_stringbuf の seekoff の実装は、
> オープンモードがin | outの場合、
> 入力、出力両方のシーケンスのストリーム ポジションを変更します。
> オープン モードがinのときは、入力シーケンスのストリーム ポジションのみ変更し、
> outのときは出力シーケンスのストリーム ポジションのみ変更します。
> 新しいポジションは、off(ずれ)とway(参照ポイント)の2つのパラメタを組み合わせて計算します。
> 位置変更前にシーケンスのカレントの位置が無効の場合、
> オペレーションは失敗し、pos_type(off_type(-1))が返り値になります。
> それ以外の場合は、カレントの新しい位置を返します。
とあるから、
>>368 は STLport 側の問題のような気もする。
401 :
デフォルトの名無しさん :2005/09/06(火) 17:36:30
あるでかいライブラリを二つ使って一つのプログラムを作りたいんですが、 片方で定義しているrealが他のライブラリでも定義されてしまっているらしく、 error: `typedef double real' redeclared as different というエラーが出ます。片方の名前をreal2とかに変えれば解決しそうなんですが、 もっと良い解決方法があったらおしえてチョ!
namespaceも使ってないライブラリは糞
>>401 namespace A
{
#include <A.h>
}
namespace B
{
#include <B.h>
}
404 :
デフォルトの名無しさん :2005/09/06(火) 17:54:21
>>403 そうして、Aのtypedef double realを使いたくて
using namespace A;
とやると、B.hのなかの他の定義ファイルは使えなくなってしまうんですよね?
B.hの他の定義は使いたいんだす。
>>404 A::real って書けばいいじゃん。
>>404 君もC++プログラマなら聞き分けたまえ。
407 :
デフォルトの名無しさん :2005/09/06(火) 18:23:34
がんばって名前変えるかな。。。
408 :
401 :2005/09/06(火) 18:24:17
サンクス>all
>>400 いやだからさ、俺のVC7.1+STLportでは、0を返さず、ちゃんと正常に-1を
返すわけよ。
>>368 と結果が違うというのはどういう事なのかと。
>>409 STLportのインストール方法が違うとか。DLLでビルドしたか、
ビルドせずに使っているかで結果が違うとか。
>>410 知らん。俺はビルドして使ってるけど正常動作した。それを言いたいだけ。
ビルドせずに使ってて不具合起きたんなら、同じビルドせずに使ってる奴に聞け。
412 :
デフォルトの名無しさん :2005/09/07(水) 00:09:34
すみません、行き詰ってしまって質問します。 現在、ビットマップ画像を読み込んで画像処理をした後に保存するプログラムを作成中なのですが、 ビットマップを表示させるところまでは出来たのですが、再描画ができません。 そこで画像処理をした画像をビットマップに保存して、再描画されるようにしたいのですがどうしたらいいでしょうか? 以下にソースを載せます。(環境はVC++6.0です)
まて
ソースはスレに書かないで別のファイルに書いてアップしたほうがいいんじゃないか? 長くなりそうだし…。
415 :
デフォルトの名無しさん :2005/09/07(水) 00:13:07
//ビットマップの初期化 void CWallChangerDlg::InitializeBitmap() { SaveBitmap.DeleteObject(); CRect ClientRect; GetClientRect(ClientRect); m_height = ClientRect.bottom-90; m_width = ClientRect.right-10; CClientDC dc(this); CDC MemDC; MemDC.CreateCompatibleDC(&dc); SaveBitmap.CreateCompatibleBitmap(&dc,m_width,m_height); MemDC.SelectObject(&SaveBitmap); MemDC.PatBlt(0,0,m_width,m_height,WHITENESS); } 初期化したSaveBitmapに読み込んで画像処理したものを保存したいのです。 (その後OnPaintで呼び出します。)
待てと言われたのに…
激しくスレ違い
418 :
デフォルトの名無しさん :2005/09/07(水) 00:19:22
>>413 、414、416
申し訳ない。書き込んでから気づきました。
あと補足。
ダイアログベースで、読み込んだ画像がダイアログ中央に出てきます。
それをSetPixel等を使って2値化 ・・・までは出来ました。
でも再描画されない・・・orz
420 :
デフォルトの名無しさん :2005/09/07(水) 00:22:40
>>417 ,419
スレ違いだったのですか・・・。板で質問するの初めてだったのでわからず、スミマセン。
どうやら2chも初めてらしい
C++でWindows上で動くファイアウォールは作れますか?
坊や…良い子だから早く寝な
424 :
デフォルトの名無しさん :2005/09/07(水) 06:33:09
C++で童貞捨てられますか?
>>424 順番が逆だ。まず童貞を捨ててからC++をやれ。そうすれば立派に禿げる。
>>409 ,411
名無しで「俺」とか言われても誰だかわからん。
tellp() が -1 を返すのが正しいと言う根拠は何?
428 :
427 :2005/09/07(水) 10:59:24
バージョン3-8-1をwindowsから使いたいのです
インスタンシエートされたオブジェクトの、静的でないメンバ関数ポインタの呼び出しは 出来るのでしょうか?
>>429 分かりにくい表現をしてるが、ごく普通のメンバ関数ポインタのことか
呼べなかったら意味ないね
431 :
429 :2005/09/07(水) 21:23:48
ごめんなさい。 やりたいことは、クラスのメンバ関数ポインタに、生成されたオブジェクトのメンバ関数を入れたい。 class A; class B { public: void (A::*func)(); }; class A { public: void print() { printf("hoge\n"); } }; int main() { A a; B b; b.func = a.print; (b.*func)(); return 0; }
>>431 C#でいうトコの delegate でそ?
それはただのメンバ関数ポインタでは無理。
boost::function 使えば出来ると思う。
まぁ単に A* と A:*func のペアを保持しといて p->(*func) とするのが、
(格好は良くないが)シンプルだと思うけど。
>>432 × p->(*func)
○ (p->*func)
boost::functionとかを使うとこうなる。 #include <cstdio> #include <boost/function.hpp> #include <boost/bind.hpp> using std::printf; class A; class B { public: boost::function<void ()> func; }; class A { public: void print() { printf("hoge\n"); } }; int main() { A a; B b; b.func = boost::bind(&A::print, a); b.func(); return 0; }
435 :
429 :2005/09/07(水) 22:13:36
>>432 ~434
ありがとう。なんとか動きました。
うーん、回りくどいことになっているのは、私の設計に問題があるらしいですね。もう一度見直してみます。
>>435 単なる予想として、インタフェースを導入してBはそれを持つのがいいような。
class Func {
public:
virtual void exec() = 0;
};
class A : public Func {
public:
virtual void exec() { … }
};
437 :
デフォルトの名無しさん :2005/09/08(木) 11:53:53
unsigned long field[4]; という、128ビット長の整数配列 field をもとに、 std::bitset<128> を構築する場合、どのようにするのが良策でしょうか? 今のところ、以下のように構築してますが、ほかにいい方法はありませんか? bitset<128> y = ( bitset<128>(field[3]) << 96 ) | ( bitset<128>(field[2]) << 64 ) | ( bitset<128>(field[1]) << 32 ) | ( bitset<128>(field[0]) );
>>437 考えたけど、あまり良い方法が思い浮かばん
#include <bitset>
#include <string>
#include <limits>
template<typename T>
std::string binary(T t)
{
std::bitset<std::numeric_limits<unsigned char>::digits*sizeof(T)> b(t);
return b.template to_string<char, std::char_traits<char>, std::allocator<char> >();
}
int main()
{
unsigned long field[4] = { 1, 1, 1, 1 };
std::bitset<128> y( binary(field[3]) +
binary(field[2]) +
binary(field[1]) +
binary(field[0]) );
std::cout << y << std::endl;
}
439 :
デフォルトの名無しさん :2005/09/08(木) 18:24:57
初心者です。VirtualAllocを使用し、構造体にメモリを割り当てようをしています。割り当ての成功or失敗は戻り値がNULLかどうかで判定できますが、何バイト割り当てられているのか①で知る方法がわかりません。 下記①の(int)sizeof(*pBmp)では、構造体のバイト数40が返ってくるので実際にアロックされたバイト数がしりたいのですが…。 /* 定数・変数定義 */ #define MAP_MAXSIZE (50L*1024L*1024L) /BITMAPINFOHEADER *pBmp; map *pMap; // メモリ獲得処理 if ((pBmp = (BITMAPINFOHEADER*)VirtualAlloc(NULL, MAP_MAXSIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)) == NULL) { return (-1); } else {/* ----- ①ここで割り当てられたバイト数を知りたい ----- */ sprintf(logMsg, "メモリリソース獲得後: pointer = BITMAPINFOHEADER %x / size = %d", pBmp, (int)sizeof(*pBmp)); pMap = (map *)pBmp; } /* 構造体定義 */ typedef struct tagBITMAPINFOHEADER{ DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER; typedef struct tag_map { BITMAPINFOHEADER biInfo;// Bitmap Info Header BYTE bData[1];// 実際には約10MB分 } map;
440 :
デフォルトの名無しさん :2005/09/08(木) 18:27:13
失礼しました。②の個所を訂正です。 /* 定数・変数定義 */ #define MAP_MAXSIZE (50L*1024L*1024L) BITMAPINFOHEADER *pBmp;// ←頭のスラッシュが余分でした。② map *pMap; // メモリ獲得処理 if ((pBmp = (BITMAPINFOHEADER*)VirtualAlloc(NULL, MAP_MAXSIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)) == NULL) { return (-1); } else {/* ----- ①ここで割り当てられたバイト数を知りたい ----- */ sprintf(logMsg, "メモリリソース獲得後: pointer = BITMAPINFOHEADER %x / size = %d", pBmp, (int)sizeof(*pBmp)); pMap = (map *)pBmp; } /* 構造体定義 */ typedef struct tagBITMAPINFOHEADER{ DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER; typedef struct tag_map { BITMAPINFOHEADER biInfo;// Bitmap Info Header BYTE bData[1];// 実際には約10MB分 } map;
スレ違い。
>>437 こんなんどうよ
template <int N>
std::bitset<32*N> make_bitset(unsigned long const(&ar)[N])
{
std::bitset<32*N> result;
for (int i = 0; i < N; i++)
(result <<= 32) |= ar[i];
return result;
}
int main()
{
unsigned long field[4] = { 1, 3, 7, 15 };
std::bitset<128> y( make_bitset(field) );
}
437,438,442の中だと442が速いね
444 :
デフォルトの名無しさん :2005/09/08(木) 19:26:56
>>438 >>442 ありがとうございます。
とりあえず、以下のようにしました。
// VC++7.1 のエラー回避用
template< typename T > struct bsizeof
{
static size_t const value = sizeof(T) * CHAR_BIT;
};
// inline bitset< sizeof(T) * CHAR_BIT * N > bitset_from_vector( ... )
// と記述するとエラーする。どうして?
template< typename T, size_t N >
inline bitset< bsizeof<T>::value * N > bitset_from_vector( T (&x)[N] )
{
typedef bitset< bsizeof<T>::value * N > bset_t;
bset_t b;
size_t i = N;
while( i != 0 )
( b << bsizeof<T>::value ) |= bset_t( x[--i] );
return b;
}
いつもオーダーで混乱するので間違ってたら指摘してください。
>>444 まあ typo だとは思うが
× ( b << bsizeof<T>::value )
○ ( b <<= bsizeof<T>::value )
>>439 VirtualQueryでは駄目だった。
VirtualFreeでもサイズは自分で入れなきゃいけないし
システムではサイズの把握までやってないんじゃないの?
だから自分で算出でいいと思うけど。
ページサイズで切り上げ( ページサイズで切り捨て( 開始アドレス ) + サイズ )
447 :
デフォルトの名無しさん :2005/09/08(木) 22:49:11
質問なのですが、クラス1で、map<string, string> sample を宣言して、 クラス2で、map<string, string>* sampleと 宣言した時、クラス1のsampleのアドレスを、クラス2のsampleに代入して、クラス2で string a = *sample[abc] とするのは 可能でしょうか?
450 :
デフォルトの名無しさん :2005/09/08(木) 23:07:31
>>448 ありがとうございます。
しかし、何度やっても”型変換が間違っています”というメッセージがでてうまくいきません。
mapをポインタとして持つこと自体が間違っているのでしょうか?
それとも、クラス2で、string a = *sample[abc] という書き方が間違っているのでしょうか?
452 :
デフォルトの名無しさん :2005/09/08(木) 23:24:48
>>448 >>449 >>451 みなさんありがとうございました。
ご指摘どおり型変換に問題があったのですね。
早速明日再度試してみたいと思います。
本当にありがとうございます。
型変換じゃなくて演算子の優先順位の問題だろ。
454 :
デフォルトの名無しさん :2005/09/09(金) 00:19:45
455 :
デフォルトの名無しさん :2005/09/09(金) 01:27:29
累乗を一行で演算子で表せれますか? 10^xを計算したいんだけど
>>455 累乗演算子はC++にはないよ。
代わりにpow関数を使う
457 :
435 :2005/09/09(金) 01:35:48
クラスの継承時における、アクセス演算子についてなんですが 例えばある基底クラス内でprotectedなメンバ変数を宣言して、そのクラスを継承した場合 このprotectedなメンバ変数は、派生クラスのメンバ変数としてpublic指定をしたとほぼ同意になりますか? それとも、privateで宣言したようなものですか? 手持ちの入門書だと継承先で使用できるとしか書いてなくて迷っています。
>>458 試せよ。人に聞くよりそのほうが覚える。
>>458 そのとおり継承先のクラスからでしか使えないから。前者の意味はpublicで十分だろ。
class B
{
public:
B(int n) : hoge(n) {} //OK
int get() const {return hoge;}
protected:
int hoge;
};
class D : public B
{
public:
void set(int n) {hoge = n;} //OK
};
int main()
{
D obj(5);
std::cout << obj.hoge << std::endl; //エラー
std::cout << obj.get() << std::endl; //OK
}
>>458 元々protectedだったメンバは絶対にpublic扱いにならないし、元々privateだったメンバは絶対にprotected扱いやpublic扱いにならない。
「: protected」をしたら継承されたメンバは絶対にpublic扱いにならないし、「: private」をしたら継承されたメンバは絶対にprotectedやpublicにならない。
あっという間に試せることなのに、なんでいちいち質問するんだろうね。 手を動かさないからいつまで経っても成長できないんだよ。
試してもコンパイラが間違ってるかも知れないって事だろ?
466 :
461 :2005/09/10(土) 11:18:05
>>465 あぁ、そうか。461の言い方はマズかったな。
char型のポインタをcout文で使うと 文字配列のアドレスじゃなくて文字列を表示するのはなぜなんですか?
>>467 そういうオーバーロードが用意されているから、としか答えようがない。
アドレス値を表示させたければキャストすればいい。
char *p = ~;
std::cout << static_cast<void *>(p) << std::endl;
そういう仕様だからです
仕様ですかぁー なるほど
そうしないと文字列を文字列として<<で出力できなくなる。
472の馬鹿が逆に晒されてしまいました。
>>474 アクセス権限なんてusingで自由自在
>>475 いや、usingでは隠すほうに持っていけない。
>>475 あ、どうも。usingってnamespaceの省略以外にも使い道があるんですねぇ。
そこで無名名前空間ですよ
>>478 いや、namespaceの話じゃないから
480 :
デフォルトの名無しさん :2005/09/12(月) 14:53:28
boostをインテルコンパイラで使用するためにインストールしました。 疑問があるのですが、ここで質問してもいいですか?
>>480 質問していいか質問するなんて行為は辞めれ
いきなり本題でok
483 :
デフォルトの名無しさん :2005/09/12(月) 15:45:53
ファイルにクラスの状態を保存する為、そのクラス用にoperator<< 関数を作りたいと思います。 しかし同時に、デバック表示用に人が読める形で出力するoperator<<関数も欲しいんですが どう作り分ければ良いですか? std::ostream& operator<< ( std::ostream& stream, const ClassA& a ) const; これでは被ってしまいます。
インストールに関する質問で恐縮ですが、こちらで質問します。 Visual Studio .NET 2005 + intel C++ compiler ver.9 の環境に下記の様にビルドしました。 bjam -sTOOLS=intel-win32 "--prefix=C:\Program Files\Intel\Compiler\C++\9.0\IA32" "-sINTEL_PATH=C:\Program Files\Intel\Compiler\C++\9.0\IA32" "-sINTEL_BASE_MSVC_TOOLSET=vc-7_1" install インテルコンパイラ用にビルドしたつもりですが、 vc-C++ bin\boost\libs\wave\build\libboost_wave.lib\intel-win32\release\threading-multi\cpp_re.obj cpp_re.cpp とvc-C++でコンパイルしていきました。これでよいのでしょうか? ここでビルドしたライブラリをiclで使用する予定です。
486 :
デフォルトの名無しさん :2005/09/12(月) 16:10:01
一時オブジェクトの const 参照による束縛の話なんですが、 ちと理解できたか自信ないので質問です。 こんなクラスと関数があったとして… struct A {}; struct X { const A* p; X(const A& a) : p(&a) {} }; X xget(const A& a) { return X(a); } void xtest(const X& x) { // ここで *(x.p) を使うとします } 以下のようになるという理解であってますか? これはok xtest(xget(A())); これもok const A& a = A(); xtest(xget(a)); これもok const A& a = A(); const X& x = xget(a); xtest(x); これはダメ! const X& x = xget(A()); xtest(x);
>>487 挙げている例はあってるけど、「ダメ」の理由を自分で説明できないと、
ちゃんと理解したかどうかは判別できないだろう。
>>487 ややこしいかもしれないが、一番下のはダメともいいきれない。
490 :
489 :2005/09/13(火) 02:12:32
すまん、よく読んでなかった。忘れてくれ。
491 :
デフォルトの名無しさん :2005/09/13(火) 02:32:15
>>487 をみて思ったんだけど
A* p = &A();
これって、pの参照先はこのスコープが閉じるまで保持されるの?
const A& a = A(); これはダメじゃね? すぐにデストラクトされるような気が
constわけわかめ
そもそもconst T&をT同然に使える(右辺値で初期化できる)ようにというところからこうなったわけで。
497 :
デフォルトの名無しさん :2005/09/13(火) 17:35:34
RVOって関係ある?
結果には関係無いんじゃない?
499 :
デフォルトの名無しさん :2005/09/13(火) 19:21:00
お忙しいところすみませんが教えてください char s1[80], s2[80]; cout << "Enter two strings : "; gets( s1 ); gets( s2 ); strcat( s1, s2 ); cout << s1 << "\n"; で、一回目の gets( s1 ); でなぜか入力の状態にならず 勝手に NULL が入ってしまいます。 cin だと問題ないのですが 違いは何なのでしょうか?
>>499 ・gets()は過去との互換性が必要な場合を除いて使うべきではない。
・NULLは入るはずがない。NULキャラなら勿論入るが。
・
>>499 に書かれたロジック以前に入力は行なっていないか? その場合空読みするべき。
501 :
487 :2005/09/13(火) 21:23:20
>>488 一時変数の束縛は、それが参照されとぃるかどうかではなく、
あくまでその一時変数を含む式の最後まで保持されるに過ぎない、
ということを確認したかったのですが、規格書の 12.2-3 に
書いてありました。
規格書には「full-expression を評価した最後まで」みたいな表記
だったので、full-expression ってどこまでじゃーと思ってさらに
検索したら 1.9-12 に「別の expression の subexpression でない
ものが full-expression」とかあって何だか騙されたような気分に。
とりあえず関数呼び出しは expression なんで、一時オブジェクト
を使って関数呼び出しを何度行おうが、それが一つの式である限り
一時オブジェクトは有効、ということですね。一番最後の例は最初
の文の後で A() は破棄されてしまうのでダメ、と。
>>499 ios::sync_with_stdio() は呼んでますよね
503 :
デフォルトの名無しさん :2005/09/13(火) 21:33:44
>>500 > ・gets()は過去との互換性が必要な場合を除いて使うべきではない。
調べていたらバッファオーバーフローの原因になるので使わないようにと
いろんなサイトに書いてました・・・・。
fgets() というのを使うようにします。
> ・NULLは入るはずがない。NULキャラなら勿論入るが。
すみません。まだまだよくわかってないんですが、
自分でも何が言いたかったのかよくわかんないんですが
文字が入ってない状態ってことを言いたかったんです。
ヌル文字は入りますね。
> ・
>>499 に書かれたロジック以前に入力は行なっていないか? その場合空読みするべき。
>>499 のコード以前に cin で入力させていました。
これを消してやってみたら、問題なく動きました。
どういう動きをしてこういうことになるのかとか
細かいことはまだまだよくわからないんですが
これから勉強続けていけばわかってくるかなということで
今回はこれでよしとします。
ありがとうございました。
504 :
デフォルトの名無しさん :2005/09/13(火) 21:47:22
>>502 すみません、呼んでません。
っていうか全然わかりません。
翔泳社の標準講座C++で勉強してるんですが
640ページ近くあるうちのまだ145ページぐらいしか読めてないので
難しいことはまだ全然わかりません。
でもちょっと調べてみます。
ありがとうございました。
>>504 ストリームバッファとstdioが別々の実装になっていても、常に中身を同じく
するのがstd::ios::sync_with_stdio(bool b = true)。
但し、デフォルトで最初からtrueなので、今回の件とは関係ないと思う。
>>503 一般的に、 std::cout が問題なく使える環境なら
iostream と cstdio は混ぜる必要が無い。(混ぜないほうがいい)
さらに言えば、文字列操作も std::string を使ってしまえばいい。
今回の例で行くと、 s1 に40文字、 s2 に40文字入力された場合、
strcat() で配列サイズ超えた書き込みが起こってしまう。
string s1, s2;
cout << "Enter two strings : ";
cin >> s1;
cin >> s2;
s1 += s2; // or s1.append(s2);
cout << s1 << "\n";
これでバッファオーバーフローも配列オーバーも起こり得ない。
ただし cin >> s1 はDOS攻撃を許してしまう
セキュリティホールだと捉える場合もある。
istream::getline() などを使うといい。
ポインタについて質問させて下さい。 以下の2つの宣言は、同じ意味を持ちますか? CPen* Pen1; CPen *Pen2; 基本的なことの質問ですが、回答お願いいたします。
前者はCPen*型の変数Pen1を宣言している 前者はCPen*型の変数Pen2を宣言している 質問の意図を察するに同じ意味でオッケー。
>>508 上の宣言はC++コンパイラを使うように指示する
下の宣言はCコンパイラを使うように指示する
512 :
デフォルトの名無しさん :2005/09/14(水) 01:57:37
えーっ!そうなのか!!知らなかったよ。 んじゃ CPen * Pen3; はどうなるの?教えてちょぶだい。
C#コンパイラかな、やっぱり。
CPen * * Pen4, *pen5; は?
516 :
508 :2005/09/14(水) 04:13:38
>>509 早速のレスありがとうございます。
>>510 本当のことですか?ネタですか?
マジレス、キボン
さすがにこのレベルなら自分で調べられるだろ
>>516 >>511 以降の展開見れば察しはつくだろ。
察しがつかないなら2chを利用するのは止めとけ。
519 :
デフォルトの名無しさん :2005/09/14(水) 07:19:56
2ch信者というやつですか。あらまあ必死 ;-)
なぜにウィンク
質問です。 try { throw (int); } catch (int a) { printf("%d\n", a); } とした場合、 aには何が入るかは決まってますか?
>>516 マジレスしとくよ。一応。お前思いっきり釣られてる。
あれれ、コンパイルできませんでした。 もしかして、型だけthrowするのってできないんですか?
つか仮にコンパイルできて0とかが返されたところで何に使うんだか。
529 :
デフォルトの名無しさん :2005/09/14(水) 10:27:34
throw int(); とやったら通りました。 型を返す時は暗黙的に一時オブジェクトを返すということですか?
>>529 int()はどんな文脈でも0と同じだが。
531 :
デフォルトの名無しさん :2005/09/14(水) 10:34:07
ちなみにaは0でした。 intの暗黙のコンストラクタは0をセットするんでしょうか。 (というかこの理解であってますか?)
>>529 言っている意味がよく分からんが、それは throw int(0); や throw 0; と書いているのと同じ。
型を返しているのではなく、int型の値(オブジェクト。内容は0)を投げている。
533 :
デフォルトの名無しさん :2005/09/14(水) 10:37:24
>>532 意味違ってましたか。
型だけをthrowしたいんですが、どうすればよいですか?
(どっかの解説サイトに型またはオブジェクトをthrowできるとあったので)
>>533 それは嘘だ。 throw できるのはオブジェクトだけ。
サイト晒せ。
>>534 そうでしたか。
すいません。
Javaのサイトだったかもしれません。
たしかgoogleで throw 例外 式 とかで検索して出てきたサイトです。
>>536 読み返したら、自分の勘違いだったみたいです。
型を投げるではなく、~型のデータを投げるという文脈みたいですね。
でも、まぎらわしいですよね。
本買えバカ
>>537 そのサイト、筆者の知識が曖昧だな。鵜呑みにしないほうがいい。
おいおい型を投げるって・・・・・ C++にはまだリフレクションが装備されてないぞ。これから先もずっとからかも。
obj->Func(); は、Func が非仮想関数なら静的結合されて、通常の関数呼び出しと同じ速度で実行できる ……の認識で合ってますか?
合ってる。 class A { public: void f(int n); }; のf()呼び出しは sturct A { }; void A_f(int n, A*) ;のA_f()呼び出し と本質的に変わらん。
thisがレジスタ渡しされるぶん前者が速いよ(VC)
const std::string & s = "hoge"; としたとき、 (1) "hoge"で初期化された一時オブジェクトが生成される (2) sに一時オブジェクトの参照が代入される という認識であっていますか? またこの場合、sの有効期間はどうなりますか?
546 :
545 :2005/09/14(水) 14:12:41
すみません。少し前に出てた話題(>487)でした。 解決しました。
>>543 >>544 便乗だけど、非仮想だったら
a->b->c->d->func()
でも同じことが言える?
質問です。 newでclassの配列を生成する際、それぞれのclass生成時のコンストラクタ引数は指定できないんでしょうか? 例えば。 String *str; str = new String [5] ("デフォ文字列"); という感じにできるのが理想です。 (Stringというのは説明のためにデッチあげたクラスです) もちろんこれはコンパイルとおらないのですが…。
C++の設計ミスでできない
ありがとうございます。 おやまぁ…。 これは結構困り者ですね。
あーん? こんな重要な事項、設計ミス以外の何があるってんだ。言って見ろ。
互換性
コンストラクタ記述にCとの互換性もクソもないと思うが
C++0xには配列のコンストラクタ記述を認める予定があるんだろ。
実際どうなんかねえ。「C++の設計と進化」を読むと、配列型のnew/delete 演算子は後から追加されたものらしいから(§10.3、P270)、その時、初期化の 書式との整合性を取るのを”うっかり”忘れたのかねえ。 俺には何か理由があってわざと取り入れなかったような気がしてならないんだが。
>>548 代わりにその型へのポインタをnew []して、その中に個々の要素をnewで入れたり、
あるいはstd::vectorを使って、個々の要素をpush_back()で入れていったりする。
>>558 それやと、boost::shared_ptrか、boost::ptr_vector使わないと、deleteが
面倒やねえ。
560 :
558 :2005/09/14(水) 19:43:18
>>559 言い方が悪かった。
std::vectorにはポインタではなく、オブジェクトそのものを入れるつもりで書いた。
まあ配列にはstd::vectorやね。C++なら。OOする時はboost::ptr_vector当たりが便利。
javaでもできないし良いやん
C#が出来るのでくやしい。
C# だと出来るんか。知らんかった
>>564 558の前者のようなやり方になる。つまり参照をnew []して、個々の要素をnewする。
ただ初期化できるんだけどね。
>>548 cygwin g++ なら、-ansi -Wall オプションつけても、それ通るよ。
動作も期待通り。
他の処理系のg++ は試してないからわからんけど。
C++でワイドバイトファイルとマルチバイトファイルを両方扱わなきゃ いけない場合、どのように実装する? 今は、BOMを見てマルチバイトだった場合は1行読み込む毎にwchar_tに変換~てな感じでやっている。 しかし、なんか効率悪くて思えて仕方が無いんだけど・・・。
568 :
デフォルトの名無しさん :2005/09/14(水) 20:58:04
gccとbccは独自拡張多いな‥‥まあbccはObjectPascalとの互換性維持があるからしょうがないが
gccのはもろイカ臭いよね
gccはC99とかc++0xの規格を少し取り入れているからな。C99に関してはかなり。
>>571 逆にgcc独自拡張がC99に取り入れられたものもある。
573 :
508 :2005/09/14(水) 22:45:45
>>567 読み込むファイルを全部ワイドバイトにしてしまえばいい。
で、別途コンバータを提供する。
って、そういう問題じゃないか・・・。
ワイドバイト? 新語?
ワイドバイト の検索結果のうち 日本語のページ 約 134 件中 1 - 50 件目 (1.04 秒) wide-byte の検索結果 約 630 件中 1 - 50 件目 (0.40 秒)
>>545 × sに一時オブジェクトの参照が代入される
○ sが一時オブジェクトへの参照として初期化される
stlのmapみたいな感じで、valueからkeyの検索もできるような物ってありませんでしょうか。
>>579 std::hash_map 但しSGI STL
コンパイルタイムプログラミングで template <int X> struct INT { enum { type = X }; }; としたとき、INT<100>::typeは定数値(100)になるのだろうか? というのはどうやって確かめればいいですか?
出力すればいいだろう
>>581 定数式かどうか確認したいなら typede char array[定数式]; とか。
任意の bool 式のコンパイルチェックは
template <bool> struct static_assert;
template <> struct static_assert<true> { enum { value }; };
static_assert<(100 == 100)>::value; とか。
すまん、typedef char array[定数値];
>>582-584 thx
「#defineマクロとstatic const intではなり、const intやstatic const doubleではならない」
ものって即値と呼ぶのだっけ。定数だとconstでしたごめんなさい。
コンパイル時に固定の数値として評価される値、例えばnumeric_limits<int>::min()など。
このように、コンパイル時に評価されていることを確認するのは、どうすればいいのだろう?
>>585 パフォーマンスにそれほど深刻な影響がなければ、別にコンパイル時評価にこだわる理由はない
というのはよくわかっております。
コンパイルタイムプログラミングしているつもりで、実は実行時に展開されてたら寂しいというだけの理由です。
そんなに不安なら逆アセンブルなりなんなりすればいいじゃん。 VCならデバッグモードで確認できるし、gccなら-Sオプションつけてコンパイルしてもいいけど。
>VCならデバッグモード ………
正しくはデュバックムォード
vctoolkitを使ってるけどIDEは無いとか?
cl -FA
593 :
デフォルトの名無しさん :2005/09/16(金) 00:38:19
C++のstreamライブラリを覚えようと 勉強してるんだけど、全然要領得ないんです。 原因は複雑な設計だったり、極端に略されたメンバ名だったりするんで なんだかやる気が起きません。 やっぱりC++使ってたらこれらが使えないと一人前とは言えないですかね?
まぁ人の好き好きだが、別なのを勉強した方がいい希ガス。 少なくとも自分はstream系が役に立ったことは無い。
他スレでVC6の bitmap<n> ってバグってるってマルチがあるけど 試したら、ホントにバグってたな やっぱりあの次期のコンパイラのSTLって過信しないほうがいいのか
iostreamは俺もcin, cout, cerrに出す時以外使ったこと無い 使いにくいから I/Oクラスが必要なときは自分で作ってる
>>596 >I/Oクラスが必要なときは自分で作ってる
馬鹿ハケーン。ま、個人レベルで何をやろうが個人の買ってだが、俺の会社に
こういう香具師が面接にきたら、一番最初に落とす。
×買って ○勝手
まぁ自分の書いた文章も確認できない香具師を落とす方が先だなw
>>598 cin cout cerr に出力するサンプルの動作だけを妄信する奴って多いからな
(サンプルがそういうの多いからか)
ここ1年、fstream sstream の実用的な使い方を知って、結構目から鱗状態だったよオレ
職業プログラマは社内のコード共有が優先で標準ライブラリの ダメな部分も使わなくちゃいけなくて大変だねえ
>>602 うちのプロジェクトなんてコンテナにSTL使わないで
MFCのコンテナ満載だよ
どうやって、こいつらにSTLを啓蒙させようかと悩み中
イテレーターとか、アルゴリズムとの絡みを上手く啓蒙できればアレ
std::stringとCStringの変換がダサい。
606 :
凶笑面 :2005/09/16(金) 02:16:17
今日の夜9時からフジTVで民俗学ミステリ凶笑面だ。 みんな、見ようぜ。 原作は新潮文庫から出てるよ。 俺はドラゴン桜を見るからビデオに撮るけどな。
Microsoftに言ってくれ
API公開したのはMSだが それに皮かぶせてMFCを売りつけた他社が 余計で中途半端なコンテナクラス(CStringを含む) をオマケで付けた弊害が蔓延してるって構図かな
>>605 std::string、std::wstring、AnsiString、WideString、CString、char*、wchar_t*が入り交じってて収拾つきません⊂(。Д。⊂⌒`つ
template<class Ctype> class A { protected: Ctype foo; }; template<class Ctype> class B : public A<Ctype> { void bar() { foo = 0; } }; こんな感じな事をやろうとすると、 error: ‘foo’ was not declared in this scope と怒られてしまいます。 Aの継承をintなどで限定するとこのエラーは出ませんでした。 Ctypeのまま継承するにはどうしたらいいでしょうか。
>>612 template<class Ctype>
class A
{
protected:
Ctype foo;
};
template<class Ctype>
class B : public A<Ctype>
{
void bar() {
Ctype::foo = 0;
}
};
いけましたー。ありがとうございます。 しかし、なんかしっくりこないなー。C++の謎は深い。。
>>615 キーワードは
"dependant name"
"unqualified lookup"
"point of definition"
"point of instantiation"
617 :
もこな :2005/09/16(金) 14:19:14
はじめまして、私はeVc4.0++を使っている者です。 それで まずIEのように とりあえずプログラムを起動したら MSNやYahooのようなサイトのトップが表示され普通に使える物を作りたいです。 それで作ろうとしたのですが、eVcにはCHtmlViewがサポートされていないようなのでどうしたらよいのか迷ってます。 メニュー → 表示 -> ClassWizard → 関数追加 → OnInitialUpdate関数の追加 → Navigate2(_T("適当にURL"),NULL,NULL); 上記をしたら error C2065: 'Navigate2' : undeclared identifier とエラーが出てしまいました。 何故でしょうか。。。?? といいますか、IEを作るにはどうしたら良いでsしょうか。 お願いします
まずは英語の勉強からかな。
619 :
デフォルトの名無しさん :2005/09/16(金) 15:03:08
>>610 グローバルロケールの影響受けない文字列型ない?
>>617 Windows関連スレか初心者スレ、或いはeVcとやらのスレへどうぞ。
>>593 ほか
i/o/iostreamクラスに限って言えばは単にCのFILE *のラッパのような感じだよ。(<<と>>以外は)
std::stringに対し"頭のスペースを削る"とか "doubleに変換"みたいな事が出来る関数ってありませんでしょうか? 自分で書くしか無いんでしょうか。。
>>622 doubleに変換→boost::lexical_cast
頭のスペース削る→boost::regex
>>622 少なくとも後者はstringstream使うと楽にできる。
前者はそのままでも可能。
>>622 頭のスペースはfind_if+erase
後者だけ。 #include<sstream> double toDouble(const std::string&s){ double ret; return std::stringstream(s)>>ret,ret; } boost::lexical_castを使う方がより良いけど
//doubleに変換 double conv2double(const std::string foo) {return std::atof(foo.c_str());} // 頭のスペースを削る std::string cutSpaces(const std::string foo) {return /* すまん、後を頼む */}
じゃあこんな感じで std::string cutSpace(const std::string & foo){ return std::string(find_if(foo.begin(),foo.end(),std::bind2nd(std::not_equal_to<char>(),' ')),foo.end()); }
おっとstdの付け忘れがあった。 ×find_if ○std::find_if
すみません、「禿本」とは何を指しているのでしょうか? VisualC++のスレッドで間違えて聞いてしまいましたが 皆様にC++スレで聞けと仰られたので、、、
>>632 ありがとう、早速注文したよ、AMAZONで
boost::trim_left
gcc で日本語の正規表現が使いたいのですが、適当なライブラリはあるのでしょうか? boost::regex を試してみましたが、うまく動いてくれませんでした。
>>630 たかがこれだけの事で写真まで載せるあたりがアメリカンだね
>>637 CodeProjectのAuthorはアメリカ人じゃない人の方が多いけどな
日本にはCodeProjectみたいなのはないの?
1 AAA 3 xxxx 10 aaaaa 3 qqqqq 3 aaaaaaa こんな感じのデータを保存していきたいんですが、 データを取り出すときに、同じ数字のデータごと集めて出したいんです。 (1のデータはaaa,bbb,ccc。3はddd...といった感じで) vectorやmapで保持すると、取り出すときに数字を一々確認するような形になってしまうのですが、 より良いデータの保持、取り出し方法はありませんでしょうか。
std::multi_map
std::ifstream f;の中身を 全部文字列にしたいときってみんなどうしてる? std::stringstream s; s << fi.rdbuf(); std::string result(s.str());
>>643 std::istreambuf_iterator<char> begin(fi),end;
std::string result(begin, end);
645 :
643 :2005/09/18(日) 07:13:34
>>644 なるほどそうやるのか~
でも、VC6タソだとだめぽ...
>>640 欲しいねぇ。flipcodeも閉鎖(Readonly化)しちゃったし・・・
647 :
デフォルトの名無しさん :2005/09/18(日) 14:31:15
猫でもわかるのページの C++のページの26章のファイルの入出力のところで 実行するとファイル名は入力してファイルができるのですが文字が書きこめません。 解かる方教えていただけないでしょうか?
初心者スレへでもどうぞ。つーか、URIくらい提示しろって。
文字列定数を宣言したいときってどっちが速度とかメモリの効率がいいですか? const char* const str = "test"; const char[] str = "test";
651 :
649 :2005/09/18(日) 14:55:42
あと、関数内で 文字列定数定義する場合 const char* const str = "test"; const char[] str = "test"; より static const char* const str = "test"; static const char[] str = "test"; の方が効率いいというのは本当ですか?
const char[] str = "test"; こんな書き方C++で出来たっけ?
653 :
649 :2005/09/18(日) 15:24:15
>>652 とりあえず手元のVC++7.1ではコンパイル通るのですが、
これってVC++独自拡張でしょうか?
const char str[] = "test"; これじゃなんでだめなの?
655 :
649 :2005/09/18(日) 15:32:56
bcc5.6.4とg++3.4.3で試したら通りませんでした。 独自拡張だったようです。const char* constの方を使う事にします。 staticの方は関数内では付けた方がいいんでしょうか?
>>654 俺んとこで試したら main 関数がないってエラーがでたよ。
657 :
649 :2005/09/18(日) 15:36:08
すいませんやっぱりg++でもbccでも通りました。 const char str[] = "test"; ですよ? const char[] str = "test"; ではなく。
658 :
デフォルトの名無しさん :2005/09/18(日) 15:36:31
コンパイル通らないけど?これ。
const char[] str = "test";
>>649 いくらか効率に違いが出るかも知れんが、そんな些細な効率化を意識するよりstaticやchar*、char[]の使い分け方を理解しろって。
状況によって使い分けるものを一緒くたに語ってもしょうがないだろ。
659 :
649 :2005/09/18(日) 15:38:29
#include <iostream> const char str[] = "test"; int main() { using namespace std; cout << str << endl; return 0; }; これそのままコピペしたら通ると思います。 結局どっちがいいんでしょうか?
アセンブラのソース見れば一発じゃん
すいまらん最初の方に const char[] strとか自分で書いてました。 const char str[]が正解です。
662 :
649 :2005/09/18(日) 15:42:08
>>660 それが一番手っ取り早そうですね。
ありがとうございました。
const char* const str = "test"; const char str[] = "test"; 最適化すれば、この二つって意味的に同じ物になる?
全く違います
>>664 どういうときに?ポインタのアドレスを取るようなコードがないとしたらどう?
666 :
649 :2005/09/18(日) 15:50:50
>>663 違いました。
コンパイラが吐いたアセンブラのリスト見れば分かります。
コンパイラの最適化ってまだそんなもんなんですね。
667 :
649 :2005/09/18(日) 15:51:50
ちなみにアセンブラリストは cl -G7 -O2 -GF -FAs test.cpp で吐かせました
ポインタ1個分
考えるまでもなく前者 後者は存在意義自体疑問
#define str "test" が最強 最適化されるコンパイラ多数 Cでも使える
int _tmain(int argc, _TCHAR* argv[]) { const char* const str0 = "test"; const char str1[] = "test"; static const char* const str2 = "test"; static const char str3[] = "test"; #define str4 "test" std::cout << str0; std::cout << str1; std::cout << str2; std::cout << str3; std::cout << str4; return 0; } これだと、 str4 = str3 > str2 > str0 > str1
void sub(); int _tmain(int argc, _TCHAR* argv[]) { const char* const str0 = "test"; const char str1[] = "test"; static const char* const str2 = "test"; static const char str3[] = "test"; #define str4 "test" std::cout << str0; std::cout << str1; std::cout << str2; std::cout << str3; std::cout << str4; return 0; } void sub() { puts(str4); } #defineキモッ
>>651 本当だよ。
関数ローカルでの
const char str[] = "test";
は、
・ローカルなメモリ領域(一般的には関数のスタックフレーム内)
・初期化するためのデータ(この場合では"test")
・初期化するためのコード(この場合ではmemcpyとか)
を必要とする。
それに対して
static const char str[] = "test";
なら "test" の実体を静的に用意すればいい。
"test"とstrがどのセクションに割り当てられてどういう風に初期化されるっかてことだろ。
struct hoge { size_t size; void *data; }; のdataが指し示すsizeバイトのヒープメモリを解放するには、 どうすりゃいいんですか? 適当に、delete[size] (char*)data;とやってみたら、コンパイルは通ったけど、 違う?
void*ってことは何がくるか分からないってことなのか? 素直に考えればインターフェースに分離するかテンプレートだと思うが。
>>679 new char [...]で確保したことが確実なのならまあそれでいいんだが
それ以外の確保の可能性があるのなら(mallocやnew 他の型)駄目
確保方法によって方法変わるからどうやってメモリ確保したか教えて。
dataは様々な構造体で確保したデータを指します。
684 :
679 :2005/09/18(日) 21:53:30
struct Apple; hoge h; h->data = new Apple; h->size = sizeof(Apple); みたいな感じです。
ついでにtypeidも取得しといたらどうだw
struct Object{ virtual ~Object(){} }; struct hoge{ size_t size; Object*data; }; とかにして使う型をObjectから派生させちゃ駄目ですか?
素直にテンプレートでも使おうよ。
void (*ReleaseData)(); みたいなメンバを用意して、data を設定すると同時に解放用の関数を設定してもらうとか
どうでもいいけど、様々な構造体で確保した data を、種類も知らずにどうやって使うのだろうか それとも単なるコレクション?
暇だったから 今は反省している
VisualC++なんだけど new・mallocとdelete・delete[]・freeの どの組み合わせでもリークしないんだが そういうもん?
んな訳ねーだろwwwwwwwwwwwwwww
まぁコンストラクタもデストラクタもないPODなデータ形式でかつ、 たまたまnewとmallocのメモリの確保方法が同じであればリークはしないな。 そんなコード書くやつは死んでくれた方がありがたいがな
694 :
679 :2005/09/18(日) 23:27:35
どうも。 結局、派生させました。
>>691 これリークしない?
#include <stdlib.h>
struct hoge {
int* p_;
hoge() : p_(new int[16777216]) {}
~hoge() {delete[] p_;}
};
int main() {
hoge* p = new hoge();
free(p);
}
リークもくそも無茶苦茶でんがな
ワロスw
>>691 ほい
std::vector<std::string> * p = (std::vector<std::string> *) malloc( sizeof (std::vector<std::string>) );
>>691 たしかにVCのoperator new/new[]/delete/delete[]()はmalloc/freeを呼ぶ実装になっている。
だからと言って混同して良いものではないし、コンストラクタ・デストラクタが絡むとやばい。
派生クラスやコンテナをfreeで開放するのはまずいっしょ。 deleteなら基底クラス/各オブジェクトのデストラクタを呼んでくれる。
じゃあこれならOK? class A; A* a = new A; a->~A(); free(a);
ん?ちょっと話が戻るけど
>>679 の開放はnewした時にどんな構造体かに関わらず
delete [] data;
とやるだけでnewしたときの分がちょうど開放されるわけではないの?
malloc/freeの組み合わせも同様で。
どのコンパイラだか忘れたけど、動的確保したバイト数を、newで返るアドレスの手前に保存するのがあったはず。
まあコンパイラの実装方法は多々あるのかもしれないが、newした分のバイト数は内部でしっかりとっておかないと、普通に素直なnew/deleteしたときも困らないか?
標準を知る者求む。
>>703 hoge h;
h.data=new hoge;
705 :
703 :2005/09/19(月) 02:19:11
>>704 あぁ、そういうことか。でも
h.data = new hoge; なら delete h.data;
h.data = new hoge[size]; なら delete [] h.data;
のどちらかしか使わないことように徹底した場合はどう?
まあそんな保守性低いもの書くくらいなら
>>679 みたいなの書かない方がいいわけだけど。
とりあえず、動的確保した大きさが内部で保存されてるってのは標準で保証されてるのかどうかが疑問点。
>>704 の意味がわからないんだけど
これのこと?
これならVCでは駄目だったなぁ。
struct A
{
char* a;
A(){ a = new char[100];}
~A(){ delete [] a;}
};
struct B
{
void* a;
};
{
B b;
b.a = (void*)new A;
delete b.a;
}
そんな糞なVCは窓から投げ捨てろ!
>>708 別にVCだからダメなわけじゃない。コードがダメ。
そもそもわざわざそんなコード書いて何が楽しいのかさっぱりわからん
ロマン
class B; class A { public: B method() { return B(); } }; class B: public A {} みたいな循環した宣言って無理?
>>712 無理だろうな。
基底クラスが派生クラスを知っているという状況は、一般的におかしい。
不完全型
というかBがAを継承しているなら、必要なメンバ関数をvirtualにしてA*を返せばいい話じゃ
716 :
712 :2005/09/19(月) 17:04:42
うーん、やっぱり無理か…。 Object a, b, c; a[0] = b; c = a[0] こんな感じの振る舞いをするクラスが必要になったので、最初は以下のようなコード class Assigner { nbsp;nbsp;nbsp;nbsp;... nbsp;nbsp;nbsp;nbsp;operator=(Object obj) { /* setter */ } nbsp;nbsp;nbsp;nbsp;operator Object() { /* getter */ } }; class Object { nbsp;nbsp;nbsp;nbsp;... nbsp;nbsp;nbsp;nbsp;Assigner operator[](int i) { return Assigner(this, i); } }; を書いたんだけど、これだと a[0].method(); などが動かないので、AssignerをObjectの派生クラスにしてしまおうと 考えたんだけど…。 識者の方、何か良い方法があったら教えてください。
717 :
712 :2005/09/19(月) 17:07:12
うげ。置換ミスった。 class Assigner { ... operator=(Object obj) { /* setter */ } operator Object() { /* getter */ } }; class Object { ... Assigner operator[](int i) { return Assigner(this, i); } };
確かにそのコードからだけじゃAssignerの存在価値がわからん
>>712 >>176-717 を見ていなかったときの俺ならこう答えた。
template <typename T>
class A {
public:
T func() {return T();}
};
class B : public A<B> {};
普通にvectorとかに入れときゃいいやん AとBの継承関係が無理やりすぎ
このスレはレスの多さでどれくらいレベルが低い質問なのかよくわかりますね。
>>718 ,
>>719 略しすぎて訳わかんないな。ごめんなさい。
急にコードが具体的になって申し訳ないんだけど、
PythonのC拡張を書く関係で、Pythonのオブジェクトを表すPyObjectのwrapperを書いてる。
で、Pythonオブジェクトの属性の取得/代入を[]演算子で行いたい。
value = obj["attr_name"];
obj["attr_name"] = value;
こんな感じで。なお、属性はPyObject_{Get|Set}AttrString()で可能。
class PyObjectWrapper
{
public:
PyObject* mObj;
PyObjectWrapper() {}
PyObjectWrapper(PyObject* obj): mObj(obj) {}
class Assigner
{
public:
PyObject* mObj;
string mKey;
Assigner(PyObject* obj, const string& key): mObj(obj), mKey(key) {}
operator PyObjectWrapper()
{
PyObject* pobj = PyObject_GetAttrString(mObj, (char*)mKey.c_str());
return PyObjectWrapper(pobj);
}
void operator=(const PyObjectWrapper& pobj) { PyObject_SetAttrString(mObj, (char*)mKey.c_str(), pobj.mObj); } }; PyObjectWrapper operator[](const string& key) const { return Assigner(mObj, key); } }; このコードで値の取得/代入はできるが、 obj["name"].PythonObjectのメンバ(); はできないので、AssignerをPythonObjectの派生クラスに…と考えたのです。
こう? class PyObjectWrapper { PyObject& operator[](const string& key); };
>>723-724 質問をぶった切ることになるけど、 boost::python でも見るといいんじゃないかな?
勉強じゃないなら、そのまま使うとか。
>>723 , 724
アドホックな解決策として、Assignerで
PyObject *operator->() const {
return mObj;
}
としておけば、
obj["name"]->メンバ();
は使えるようになるんじゃまいか。
boost::python使うのが一番手っ取り早いだろうけど。
728 :
デフォルトの名無しさん :2005/09/19(月) 20:33:00
COMのスレってどこいっちゃったの?
int *i; i = new int[x]; 動的に確保した配列の数(x)をどうやって算出するのか おしえてください。
基本的にはできない。 別変数に個数を保存しておくか、vectorのように配列のサイズを知ることができるコンテナを使う。
>>733 すいません。
g++ .... -c mqodrawer.cc -o mqodrawer.o
material.hh:22: error: ‘Vector4’ has not been declared
material.hh:22: error: expected ‘,’ or ‘...’ before ‘<’ token
material.hh:23: error: ‘Vector4’ has not been declared
material.hh:23: error: expected ‘,’ or ‘...’ before ‘<’ token
material.hh:24: error: ‘Vector4’ has not been declared
material.hh:24: error: expected ‘,’ or ‘...’ before ‘<’ token
...
こんな感じのエラーです。
>>734 そのまんまじゃねーか。
↓これだろ。
//#include "vector.hh"
#include "texture.hh"
namespace bkl {
#include "vector.hh"
Vector4 が ::bkl::bkl::Vector4 になってる。
::bkl 内で Vector4 では見つからない。
こんなことになるから、 namespace の中で #include するな。
>>735 すいません。それはnamespaceの外でincludeしても同様のエラーが出ます。
元々外のコメントアウトされたものだけだったんですが、見つからんと言われたので
色々書き換えてたのが残ってしまっていました。
#include "vector.hh"
#include "texture.hh"
namespace bkl {
//#include "vector.hh"
このようにしても、エラーコードはかわりませんです。。
>>736 手元の 3.4@cygwin では、その修正で問題なくなる。
エラーメッセージが変わらないわけ無いとおもうんだが。
もう一度試しても、本当に >734 のエラーになるか?
エラーメッセージはそのままコピペしてるか?
>>737 はい、全く同じエラーになります。自分の環境(FedoraCore4)のgcc3.2でも通ります。
が、gcc4では通りません。。
まさか…gcc4環境からそのヘッダにパスが通ってないとか言わないよな… だとしたら死んでも償いきれないぞっ!!
usingディレクティブである名前空間を丸ごと可視化しようとして、シンボル名が衝突してしまいます。 名前空間を直接指定してスコープ解決すればいいのはわかっていますが、 小手先の方法として、あるひとつのシンボルを優先して解決するような方法はいまりすでしょうか。 本当はそうならないように設計すべきだということはわかっているのですが…… お願いします。
>解決するような方法はいまりすでしょうか。 いまりません。
いまハムスターです
>>738 同じディレクトリにあるヘッダですし、
他のファイルからもincludeされているヘッダなのでそれはないです。
何故出来ないんだろう。。
freopenを使わないでstd::coutをファイルにする方法ってないの?
リダイレクト
>>744 逆に、どうやってstd::freopen()を使ってstd::coutをファイルにするのか聞きたい。
747 :
744 :2005/09/20(火) 12:50:57
>745 リダイレクトってOSの?それでは駄目だ。 >746 ごめん。std::freopenではなくて、Cのだ。
普通そういう場合は設計段階から考慮して、ストリームをostream&なりで保持して 後から切り替えができるようにするもんじゃないか
クラスをポインタ型で宣言して メンバ関数のアドレスを取得しようとすると 「仮想関数のアドレスを取ろうとしました」って言われる CGame *game; game = new CGame; &(game->Main); // エラー こんな感じ なんで仮想関数?
>>749 CGame::Mainが仮想関数なんじゃないの?
ただのvoid型 ソース全部検索したけどvirtualって文字列は CWinAppの派生クラスに1コだけだった
>>749 それはVC++の意味不明なエラーメッセージで混乱してるだけ。g++でコンパイルしてみ。
「ISO C++ではそのようなアドレス取得は認められていません」って出るから。
>>749 game->Main(); ではないかと釣られてみる。
そりゃ残念だ どうしても手動でメモリ確保しつつ関数のアドレスが欲しかったんだけど 教えてくれてサンクス
755 :
デフォルトの名無しさん :2005/09/20(火) 13:19:59
>>749 &(CGame::Main);じゃなんでダメなの?
関数のアドレスを取るだけなら&CGame::Mainでいいけどね。 ただしstaticにしないとコールはできないよ。 コールしたい場合はstd::mem_funか、boost::functionを使うと吉。
>>757 ていうか何でエラーが出るか理解してるか?
C++のクラスでは、オブジェクトがいくつあったところで関数の実体は1つしかなくて
その関数に暗黙にオブジェクトのポインタ(thisポインタ)が渡されるのは知ってるよね?
ということは、オブジェクトAの関数F をポインタで表現しようとなると、
オブジェクトAのアドレスと関数Fのアドレスを両方管理しなきゃいけなくなって
1つのポインタじゃ表現できないからエラーになる。
だから結局、関数だけのアドレスを取得するか(&CGame::Main)、
両方を管理できるmem_funのようなクラスを使う必要があるってだけ。
用途に応じて使い分ければいい。
インスタンスをいっぱい生成して それらのメイン関数をまとめて実行したい だからメイン関数のアドレスを集めようとしてた >C++のクラスでは、オブジェクトがいくつあったところで関数の実体は1つしかなくて >その関数に暗黙にオブジェクトのポインタ(thisポインタ)が渡されるのは知ってるよね? すいません実は・・・
>>747 こんな感じで。
#include <iostream>
#include <fstream>
int main()
{
std::ostream* fsp;
int i;
std::cout << "1: std::coutに出力 2: 'test.txt'に出力? ";
std::cin >> i;
if (i == 1)
fsp = &std::cout;
else if (i == 2)
fsp = new std::ofstream("test.txt");
else
return 0;
(*fsp) << "出力\n";
if (fsp != &std::cout)
dynamic_cast<std::ofstream*>(fsp)->close();
}
>>759 boost::signalを調べてみれば?
そこまで複雑なものじゃなくてもいいなら、ちょっと工夫すれば自作できるだろうし
763 :
デフォルトの名無しさん :2005/09/20(火) 16:47:03
下の様に、あらかじめ数が分からないintデータを、ファイルが終わるまでreadしたいのですが、 下のやり方だとreadが一回多くなってしまいます。 上手いやり方があったら教えて頂けないでしょうか。 #include <fstream> int main(){ int writed_count=0, read_count=0; std::ofstream ofile( "hoge", std::ios::binary ); for( int i=0; i<5; ++i ){ ofile.write( (const char*)&i, sizeof(int) ); ++writed_count; } ofile.close(); int array[10] = {0}; int pos = 0; std::ifstream ifile( "hoge" ); while( ! ifile.eof() ){ ifile.read( (char*)&array[pos], sizeof(int) ); ++read_count; ++pos; } printf( "write count = %d\nread count = %d\n", writed_count, read_count ); return 0; }
>>763 while (!ifile.eof()) がおかしい。
C/C++はBASICとは違い、一度読んでみて初めてEOFかどうかわかる。
従って、「読み込んでからeof()で調べてみて、okだったらやりたいことをやる」 という順序が正解ですな。 たとえば、条件文のところをwhile (1)にした上で、ifile.read()の直後にeof()をチェックして 真だったらbreakするとか、 条件文の中に読み込む式とeof()をカンマで並べるとか。
>>764 ありがとうございます、おかげで良く分かりました
この場合はreadの後にeofで終了判定すべきなんですね
>>765 リロードが間に合いませんで
なるほどwhileの所に書く手もあるんですね
重ね重ね感謝ッス
listの最後の要素のイテレータが欲しいのですが、 どうすれば効率よく取れますか? it = list.end(); --it; はマズイですよね?
>>768 std::listのイテレータはBidirectionalIteratorだからまずくない。
今ExceptionalC++を読み直してみたらまずいのは --list.end()でしたね。 ありがとうございました。
list.rbegin();
>>771 そいつが返すのはreverse_iteratorじゃないのか?
>>770 list::iterator が builtin type であることはないから
問題ないのでは?
どんなクラスへのポインタも代入できて、そのメンバ関数も実行できる型って無い? boost::anyでいけるかと思ったけど メンバ関数を実行しようとすると「boost::anyのメンバではありません」とか言われる
どんな型のポインタも代入できる、とは型がないということだ。 メンバ関数が実行できる、とは、型がある、ということだ。 型に共通のメンバ関数を括りだしてインターフェースにするか、 Object型にしてInvoke(COMMAND,...)とか、RTTIで型の列挙、 みたいな話になってくるが。
IOの [io]?strstream だけがtemplate化されてないのって何か理由あるのかな?
標準C++にstrstreamなんてないが。 basic_[io]stringstream<>ならあるけどな。
>>776 strstream類は過去との互換性のためだけに存在するから。
逆にstringstream類はテンプレートになっている。
>>777 少なくともX3014:2003には附属D.7にstrstream類が載っている。
>>774 boost::anyにoperator->を付け加えてやればできるのではないかと。
試してないけど。
どのみち型が確定しないと意味がない。
783 :
776 :2005/09/21(水) 01:11:35
どうも。
>>777 basic_iostream<...>->strstream
>>779 そのような歴史的経緯?もあり、
配列ベースの入出力のようなので今後はあまり使わない方がよさそうですね。
そこでObjective C++ですよ
どこで?
>>784 微妙に使いどころに苦しむ。
オブジェクトに互換性がないんじゃ、混ぜて書けるメリットが無いと思うんだが。
つか、むしろC++ベースでCocoaをサポートしてくれ
787 :
635 :2005/09/21(水) 16:47:08
>> 638 情報ありがとうございました。鬼車の c++ ラッパーを作って、ruby-like な gsub とか scan ができるようになりました。日本語の正規表現も問題なしです。
鬼車で解決したみたいだからどうでもいいけど、 日本語で問題があったならwregexだとどうだったんだろうか。
PC一般板の、エスパースレから誘導されてきました。 よろしくお願いします。 c++で作られたソフトをダウンロードしたのですが 文字が一部「・」とか「・・」と表示されていて 読めません。 どうすれば日本語に戻りますか?
790 :
デフォルトの名無しさん :2005/09/21(水) 18:25:20
参照仮引数と、ポインタを使った仮引数の違いは コードの書き方に違いが出るだけで やってることはおなじと考えていいんですか?
参照だとNULLを渡せないていう制約はあるけどね
こういう変態的な事したら渡せる。 *static_cast<hoge*>(NULL) まぁ自分もNULLが来ないことを前提にコード書いてるけどね
>>789 自分がそのプログラムのソースコードを修正する気でもない限り、ここは板違い。
恨むならエスパースレでお前にここに行けと答えた奴を恨め。
795 :
790 :2005/09/21(水) 20:15:18
前勉強したときはなんか頭混乱して よくわからなかったままだったんですが、 今回勉強し直してたらおんなじなんじゃないかとおもいまして お聞きしました。 すっきりしました。 さんくすです。
796 :
デフォルトの名無しさん :2005/09/21(水) 20:19:58
クラス内で定義されたタイプはなんて呼んだらいいんでしょう? メンバータイプでぐぐると異様に件数が少ないんですが・・・
>>789 EUCかUTF-8かSJISかいろいろ試せ。
798 :
635 :2005/09/21(水) 23:02:51
>>788 gcc with boost::regex (wregex) だと、正規表現自体に日本語を含むケースでまともに
動きませんでした。原因は良く分かりませんが・・・。
>>796 クラス内で定義されたクラス型なら
"nested class" 「ネストされたクラス」っていう呼び方があるけど、
typedef だと特に用語も無く「クラス内の typedef 」とか言えばいいと思う。
800 :
デフォルトの名無しさん :2005/09/22(木) 05:50:42
自分のクラスをintの参照にキャストしたい場合、 class AAA { public: operator int&() { return & m_i; } int m_i; }; という具合に自分のメンバのm_iのポインタを返せばいいのですか? 正しい方法を教えてくださいませ。
>>800 参照とポインタは違う。やればすぐ判ることを一々聞くな。
そもそも、メンバを返すのが適当な設計かどうかは一概には言えんぞ。
それと、constメンバ関数にしておいた方がいいかも知らん。
802 :
初心者 :2005/09/22(木) 13:20:24
質問があります。 現在、ボーランドでプログラムを作っているのですが、 TransparentBlt()関数が読み込めないらしく、 Error: 外部シンボル 'TransparentBlt' が未解決 と出てしまいます。 何かをインクルードし忘れているからでしょうか? windows.hだけをインクルードしているのですが。
804 :
デフォルトの名無しさん :2005/09/22(木) 13:42:18
以下のようなMakefileでコンパイルしているのですが、$(EXE)を生成する時は、$(CC)により指定しているコンパイラを 使ってくれるのですが、$(OBJS)を生成するときは、g++が使われてしまいます。拡張子ルールか何かがまちがっているのでしょうか? どなたかご教授をよろしくお願いします。 環境は、Red Hat(R) Enterprise Linux AS 2.1 /************* Makefile ****************/ CC = /opt/intel_cc_80/bin/icc DEBUG = -g CFLAG = -c $(DEBUG) OFLAG = -o IPOFLAG = -ipo IPFLAG = -ip LFLAG = -lm # ソースファイルの宣言 SRCS = Main.cpp HelloWorld.cpp OBJS = ${SRCS:.cpp=.o} # 実行ファイルの宣言 EXE = Ocean $(EXE) : $(OBJS) $(CC) $(OFLAG) $(EXE) $(IPOFLAG) $(OBJS) $(LFLAG) .c.o : $(CC) $(CFLAG) $(IPOFLAG) $< Main.o : HelloWorld.h HelloWorld.o : HelloWorld.h
>>804 .cpp.oはデフォルトでどう定義されているのか見てみるがよろし。
806 :
初心者 :2005/09/22(木) 13:55:17
807 :
804 :2005/09/22(木) 13:56:20
>>805 c++のプログラムでしたので、
.c.o => .cpp.o
と、変更したら解決できました。ありがとうございます。
ほんとしょうがないミスで申し訳ありません。
.c から .o を生成する規則を自分で記述しときながら、実際の SRC は .cpp の群 .cpp から .o を生成する規則を追加汁
809 :
デフォルトの名無しさん :2005/09/22(木) 21:50:36
今晩は、教えてください。 ウィドウに、文字を書き込んでいるのですが、 一定の処で、改行したいのですが、 どうも、区切り場所の文字が、変になります。 バイト数を求めるには、どうすればよいのでしょうか string hh; hh = strtok(NULL,"\t"); while(1){ if(strlen(hh.c_str())>=25){ TextOut(ps.hdc,105,takasa,hh.substr(0,24).c_str(), strlen(hh.substr(0,24).c_str())); hh = hh.substr(24,hh.length()); takasa +=20; }else{ TextOut(ps.hdc,105,takasa, hh.substr(0,hh.length()).c_str(), strlen(hh.c_str())); break; } }
なぜだめなのかを考えなさい 意外と簡単だから
strlen(hh.c_str()) ってずいぶん斬新なコードだなぁ、
string使う意味が全くないな
813 :
デフォルトの名無しさん :2005/09/22(木) 22:26:49
>>810 さんありがとうございます。
何度かんがえてもわかりません。
上のコードでは、最後の文字が半角なら
失敗しす。
だから、最後の文字が半角かどうか判断して、
コードを変えようかと思ったのですが、
もっと簡単な方法があると考えてよいのでしょうか。
そうならば、もっと考えて見ます。
>>811 さん、全く読みにくいコードをあげてしまいすみません。
c も c++もまったくしらず、vc++からはじめたので、
charのポインターつかうか、stringクラスつかうか、
あるいは、この関数がどっちの関数なのか、
整理が全くできてない状態です。
814 :
デフォルトの名無しさん :2005/09/22(木) 22:28:59
>>812 さんへ
string 使うと、メモリの心配しなくてすむのかなと思ったのですが、
malloc とか、使わなくてすむと・・・
>c も c++もまったくしらず、vc++からはじめたので、 こいつは大物になるぜ。
>>814 std::string.length()のこともたまには思い出してあげてください。
とりあえずstrlen(~.c_str())は~.length()に直せ。
> hh.substr(0,hh.length()).c_str(), 目から鱗が落ちた。
昔見たstr[strlen(str)] = '\0';並にヒットだ俺的に。
VB厨臭い使い方だよなあ。MID$のような。
未来の大物が降臨しているなw ところで皆に聞きたいんだが、クラスのメンバである配列の初期化ってどうやってる? 自分のやり方むちゃくちゃな予感なんで定石を聞きたいんだが。
>>822 むちゃくちゃなやり方知りたいので書いて
>>822 普通のCスタイル配列じゃコンストラクタ関数の先頭で、とか無理だから
別にないと思うよ。
参照をメンバに持つクラスを複数持ちたいときハマるよね。
826 :
822 :2005/09/23(金) 00:08:53
class Color { union { float color[4]; struct { float c1; float c2; float c3; float c4; }; }; Color(void) : c1(0.0),c2(0.0),c3(0.0),c4(0.0) {}; Color(float* c) : c1(*c),c2(*(c+1)),c3(*(c+2)),c4(*(c+3)) {}; }; こんな感じでやってる。
>>826 float4つだからAltiVecかSSEのコードかと思った。
>>826 組込型なら、そういう場合は割り切ってコンストラクタの中で記述するのがいいかと。
829 :
822 :2005/09/23(金) 00:25:38
そんなもんか。㌧㌧
>>819 strを単なる文字型の配列として使っていたら最後が'\0'で終わってるとは限らないから有効なんじゃ、と
一瞬思ってしまったorz
'\0'で終わってなかったらstrlen使えないよな。sizeofならともかく。
BCCでコンパイルしたときSleepが未定義の関数ってなるのは俺だけ?
>>831 必要なライブラリにリンクしてても出るんなら
あんただけ。
イテレータってポインタの代わりとして長期間保持していてるのって普通? それともイテレータは基本的に複数要素に順番にアクセスするために あるのであって、単にコンテナ内の一つの要素のアドレスを 長期間保持して好きなときに要素にアクセスしたいだけ(ptr++等のポインタ演算も行わない) の場合、生ポインタを保持しておいたほうがいいの?
834 :
デフォルトの名無しさん :2005/09/24(土) 12:42:56
質問です。 演算子のオーバーロードは継承した場合引き継がれないのでしょうか。 クラスで演算子のオーバーロードをしました。 class CBase{ (略) void operator =(CBase*); }; で、その後CBaseを継承したクラスを作成 class CMain : public CBase{ (略) } void main(){ CMain a; a = new CBase(); } としたところコンパイルエラーなのです。 ためしに class CMain : public CBase{ (略) void operator =(CBase*); } としてみたところ、コンパイルがとおりました。 つまり演算子のオーバーロードは継承されないのかなと感じたわけです。 これはそうなのでしょうか。
>としたところコンパイルエラーなのです。 内容書けや
>>833 イテレータは、ポインタの概念を大きく拡張したもの。
君の言っているポインタは、random access iteratorの事だと思うが、
C++ STLのコンテナや、ストリームは、自由にあちこちをアクセスできない
物がある。
イテレータをそれぞれの属性を持った物として定義する事により、その
コンテナやストリームの意味を逸脱しない範囲でアクセス出来るように
なっている。
それから、長時間保持するとあるが、コンテナのメンバ関数にはイテレータ
を無効にする物があるので、保持しても無意味。
>>833 イテレータが無効になるタイミングを把握しているのなら、
長期間保持してもいい。
イテレータとしての操作が不要であれば、
生ポインタのほうがサイズや処理効率の面で
パフォーマンスがいいこともある。
>>836 map や list などのイテレータは、
指してる要素の削除以外では無効にならないんで、
長期間保持するのはよくあることだよ。
>>834 演算子のオーバーロードも継承される。
ただし代入演算子の場合はうまくいかない。
同じクラスの代入用 T& operator = (T const&) はクラスを定義ごとに必ず宣言される。
ユーザーが宣言しなくても、コンパイラが自動的に宣言する。
前者のケースではコンパイラが自動的に追加した宣言によって
CBase の operator = が隠れてしまっている。
>>838 あらー、代入演算子だけはダメなんですか。
ありがとうございます。
いちいち代入演算子のオーバーライドに長々プログラム書くのはアレなので、
CBaseにInsert()という関数を作ってそれを呼ぶようにします。
void operator =(CBase* p){
insert(p);
}
>>835 失礼しました。
error C2679: 二項演算子 '=' : 型 'class Image *' の右オペランドを扱う演算子は定義されていません。(または変換できません)
でした。
>>839 そんなことするぐらいなら、全部 Insert() 使ったほうがいいぞ。
ただ便利だからと言うだけの理由で
組み込み型と意味の違う代入演算子を作るのはよくない。
さらに、 >834 の例だと a = 0 なんてコードもコンパイルが通る。
new の戻り値を生ポインタで受け取るのも危ない。
>>837 例えばstd::mapが赤黒木で構成されているとして、挿入後回転や二重回転
が起きてもイテレータは全部有効なのか?
insert()が挿入後の新しいイテレータを返すようになっている仕様は、そういう
意味だと思っていたが。
>>840 >ただ便利だからと言うだけの理由で
>組み込み型と意味の違う代入演算子を作るのはよくない。
なるほど、確かにその通りですね。
じっくり考えてみます。ありがとうございます。
>>837 なるほど。そういう感じで使い分ければいいのですか。
ありがとうございます。
>>841 ISO/IEC 14882:1998
23.1.2 Associative containers
-8-
The insert members shall not affect the validity of iterators and references to the container,
and the erase members shall invalidate only iterators and references to the erased elements.
なので
>>837 さんが正しいです
844 :
デフォルトの名無しさん :2005/09/25(日) 07:39:18
LinuxでMPIを使ったC++コードのデバッグをVC++みたいに やるにはTotalViewとかを導入するしかないですか? フリーのデバッガでMPIプログラムのデバッグをやるのに 便利なツールがあれば教えて下さい。
>>832 ありがと。
ライブラリにリンクするの忘れてた。
オレが糞なだけだったよー。
派生クラスのインスタンスを基底クラスのポインタに入れると 仮想関数も基底クラスで定義したものに変わるの?
変わったら仮想関数の意味がないじゃない。
まさにそれを変わらないために作られたカラクリが仮想関数なんだしな
そうだよね。何がおかしかったんだろ
頭
。・゚・(ノД`)・゚・。
853 :
デフォルトの名無しさん :2005/09/25(日) 23:11:50
わかりにくかったらすみません。 Visual C++6.0なんですけど struct 1_t {int s ; int t ; int u ; } ; struct 2_t {int A[N][N] ; int B[N] ; int C[Y] ; int D[Y] ; } ; struct 3_s {struct 1_t 1_s ; struct 2_t 2_s ; int E[2] ; } 3_t[V][W] ; って感じで構造体配列をヘッダで生成して、Mainで struct 3_s *p = 3_t ; ってやってポインタ代入するんですが、新しい動作: C2440エラーってのが出ます。 色々試してみると、1次元配列にするとエラーが 出ないようなのですが。
pは3_sへの単純なポインタだから1次元配列相当 struct 3_s *p = 3_t[0];なら代入はできるだろう
855 :
デフォルトの名無しさん :2005/09/25(日) 23:21:46
>>854 早速の回答ありがとうございます。
試してみたところエラーは無くなりました。
以前そういう記述を読んだ記憶がわずかにあるの
ですが今手元に参考書が無いので確認できません。
とにかくありがとうございました。
>>853 標準では、名前は非数字から始まらなくてはならないと規定されているから、そんな名前は避けること。
>>855 struct 3_s (*p)[W] = 3_t; でもいけるだろ。こちらは二次元配列風にアクセス
できる、配列へのポインタとなる。
858 :
デフォルトの名無しさん :2005/09/26(月) 22:59:42
>>809 です
皆様、いろいろご指導ありがとうございました。
mblenを使って解決いたしました。
859 :
デフォルトの名無しさん :2005/09/27(火) 03:22:25
質問です。 暗黙のキャストが行われている箇所を明示的なキャストに変更する事によって、 処理速度が遅くなるといったことはあるのでしょうか?
ありません
>>859 暗黙のキャストを明示しただけなら、遅くなることは無い。
だが明らかに、そんなことはしないほうがいい。
dinamic_castに変更したら遅くなるかもねー
○dynamic_cast 釣ってくる
>>861 式の可読性のために明示することはあるけどね。
865 :
859 :2005/09/27(火) 03:51:09
回答ありがとうございます。
>>861 明らかにそんなことしないほうがいいというのは、
そもそもキャストする必要がないようにコードを書き直すべき、
という意味でしょうか?
C++ で以下のようなコードを書くと typedef struct { int i; } foo; typedef struct { foo foo; } bar; gcc 3.3.5 でコンパイルしたときに下記のようなエラーが出てしまいます。 error: declaration of `foo <無名 struct>::foo' error: changes meaning of `foo' from `typedef struct foo foo' 定義を変えずにこれを回避するにはどうすればよいのでしょうか? (上記の定義は C のコードとして書かれたもので、私が書き換えることはできません) 書き換えることができるなら bar の定義を次のようにすれば良いのですが... typedef struct { foo foo_; } bar;
ハードゲイ?
あ、それだけではだめだ。 struct foo { int i; }; struct bar { foo foo; };
>>871 >>864 じゃないけど、オーバーロードの絡む場合。たとえば、
unsigned char *addr;
std::cout << "addr = " << (void *)addr << "\n";
とか。
>>872 それは可読性のためじゃなくて、望みの動作をさせるために必要なんだろ。
全ての暗黙の変換を起こらないように書くことなど、実際的不可能だし意味がない
畜生。規格書にはanonymous union についてしか書いてないな。
↓これなら通るみたい。 typedef struct foo { int i; } foo; typedef struct { struct foo foo; } bar; こういう混乱を避けるため、Cのコード書くときは ・無名の struct/unon/enum は使わない。 ・struct/union/enum を省略するためだけの typedef は避ける というガイドラインを実施したほうがよさそう。
MSVCだとそのまま通るな。gccの問題か?
gcc では問題なくて、g++ で error だな。
コンパイラ換えるか、そこだけでも C(not C++)にするか…
>>866 いずれにせよ、書き換えることができない、という前提自体が間違いなので、
お好きにすれば、としかならないなあ。
881 :
872 :2005/09/27(火) 16:27:23
>>873 勘違いしてた。
でも、unsigned char *の代わりにint *ならどうよ。
>>866 元のヘッダをlegacy.hとして
$ cat legacy.h
#ifndef Legacy_H
#define Legacy_H
typedef struct {int i;} foo;
typedef struct {foo foo;} bar;
#endif
$ cat bar.h
#ifndef Bar_H
#define Bar_H
#ifdef __cplusplus
extern "C" {
struct bar;
struct foo;
#else
# include "legacy.h"
#endif
struct Bar {bar *bar_;};
struct Bar *init_bar (struct Bar *p);
int *access_foo_i (struct Bar *p);
#ifdef __cplusplus
}
#endif
#endif
(続く)
$ cat bar.c #include "bar.h" #include <malloc.h> struct Bar *init_bar (struct Bar *p) { p->bar_ = (bar *)malloc (sizeof (bar)); return p; } int *access_foo_i (struct Bar *p) { return &p->bar_->foo.i; } $ cat test.cpp #include <iostream> #include "bar.h" using namespace std; int main () { Bar b0; init_bar (&b0); *access_foo_i (&b0) = 10; cout << *access_foo_i (&b0) << endl; return 0; } $ gcc -c bar.c $ g++ -o test test.cpp bar.o $ ./test 10 でどう?
>>882 > (上記の定義は C のコードとして書かれたもので、私が書き換えることはできません)
て書いてあるからifdef __cplusplusマクロなんぞも追加できないだろう
885 :
882 :2005/09/27(火) 19:48:04
>>884 オリジナルと別に用意したラッパに加えるのはいいのでは?
>>885 ……まさかと思ったが本気のつもりでこんなコードを……
まあくそみたいな前提にはそれにふさわしい例がつくという見本として……
そのlegacy.hを使いたい関数だけCでオブジェクトファイルを作ってリンクしたらいいんでない?
>>886 ライブラリかなんかなんでしょ?
くそみたいなってのには違いないけど
>>887 つ
>>880 >>888 「ライブラリかなんか」でも無条件に書き換えられないわけではあるまいに。
どっちにしてもくそみたいなもんだが。
つか、とことん無意味に前提や条件をとり違えて問題点を見失っとるわけだが。
890 :
866 :2005/09/28(水) 00:05:44
皆さんいろいろとありがとうございます。 有効打はなさそうですね... ありがとうございました。
質問です。 operatorのオーバーライドで、 int n; CHoge c; n = c; という式を処理させたいのです。 どうにかintへの=をオーバーライドする術はないものでしょうか。
=じゃなくてoperator int()作れば?
>892 お返事ありがとうございます。 ただすいません、operator int() というのがどういうものなのか分かりません。 オーバーライド系の解説サイトはロベールさんのところをはじめ、あっちこっち見たのですが。 もしよければそれについて詳しいサイトを教えていただけませんでしょうか。
だめだこりゃ
それC#じゃね?w
了解しました。初心者スレに移動します。
ロベールさんって誰やねんw
初学者はつい目先のコンパイルエラーの解消に夢中になるあまり 考察の足りない小手先の修正をして事態を悪化させることがある。 最近デバッグ中に、某ソフトウェア・ハウスへ数年前に外注したコード中で この例の反面教師となるようなダメかつ姑息なコードを見つけて 唖然としたので晒しておく。 まずは背景解説。 class A { public: A(void) {;} //...(omit) virtual void v(void)=0; //pure virtual function }; class D : public A { D(void) : A() {v();} // pure virtual function is called! //...(omit) void v(void) {/* anything */;} }; こういうコードはC++では実行結果が不定になる。 (分かりやすく言うと書いちゃだめ。) 仮想関数のセットアップはコンストラクタの実行の どの段階で行われるか規格は敢えて厳密には決めていないからだ。 仮想関数をコンストラクタ中で呼び出すことはそもそも微妙だが、 特に純粋仮想関数の場合は深刻で、結果は不定だと明示されている。 気の利いたコンパイラなら上掲のコードについてエラーを報告するだろう。 (余談だがJavaのコンストラクタは根本的にC++と動作が違うのでOK。)
(
>>901 から続く)
で、エラーを出されたからといってその意味を深く考えないで:
class A {
public:
A(void) {;}
//...(omit)
virtual void v(void)={throw new NotCallException();}
//Non pure virtual function in the appearance only.
};
とかやって見かけ上だけ小手先で回避しようとするのはよくない。
本当に仮想関数をコンストラクタ内で呼び出す必要があるのかどうか、
もしあるならどういうタイミングでどの関数が呼び出されるか
じっくり考えてみるべきだ。
(
>>902 から続く)
まして:
class A {
public:
A(void) {;}
//...(omit)
virtual void v(void)=0;
//pure virtual function
protected:
void bypass(A* a) {a->v();}
};
class D : public A {
D(void) : A() {bypass(this);}
// Ooops!! pure virtual function is called!
//...(omit)
void v(void) {/* anything */;}
};
などとやってコンパイラを出し抜こうと考えるのは
以ての外である。
これはコンパイラが検出可能だったシンプルな問題を
ロジックをスパゲティ化することで
コンパイラにも人間にも
見つけにくい実行時エラーに変えて
隠蔽したに過ぎない最低のコードになる。
宣伝死ねって事でいいんだろうか
最初は愚痴の部分まで一気に書きかけたが、 誘導される前に自己誘導&自粛したってことで。
愚痴の部分抜いたら初心者でもマトモな脳みそがあれば 自分で分かるような事を偉そうに書いただけになるんだが。
長すぎ。3行で飽きて読むのやめた。
>>901 コンストラクタ内で仮想関数を呼び出したときの動作については
規格中に記述があるよ。 12.7.3 がそう。
D(void) : A() {v();}
ここでは D::v() が呼び出される。
そして D::v() は純粋仮想関数では無いので、
呼び出し自体に問題は無い。
偉そうな長文が間抜けだな。
偉そうな奴は大抵間抜けだからな。
912 :
デフォルトの名無しさん :2005/10/02(日) 02:05:03
メンバ関数ポインタのポインタをtypedefを使わずにどのように定義したらいいんでしょうか? typedef void(*ClassName::Func)(); Func* f; のFunc*をtypedefを使わずに定義したいんです。 単なるメンバ関数のポインタなら void(ClassName::*f)(); でいいんですが....
914 :
デフォルトの名無しさん :2005/10/02(日) 05:03:17
std::string型の変数に"2.5"や"4.7"などの小数点を含む数字の文字列が格納されているのですが、 これを数字として扱って加減乗除するにはどうすればいいですか?
こんな感じかな std::string s = "2.5"; double x; std::sscanf(s.c_str(), "%lf", & x);
>>915 いい加減Cの呪縛から逃れろ。
>>914 boost::lexical_cast<double>(str)を使うか、std::stringstream s(str); s >> d;
などどやる。
>>915 C流でやるならせめてstd::atof(s.c_str())にしてくれ。
>>912 俺もそのままtypedef使えとは思うが、こういう手段を知っていても損はないと思う。
#include <iostream>
#include <typeinfo>
class ClassName {};
typedef void (*ClassName::Func)();
int main()
{
std::cout << typeid (Func *).name() << std::endl;
}
>>916 C++は両方とも糞重いのが難点
まあlexical_castも中でstringstream使ってるから当たり前だけど。
920 :
914 :2005/10/02(日) 10:49:27
貧弱シンプルC路線で行くか重厚楽々C++路線で行くか
それを好きに選べることがC++のいいところでもある。
でも単なる変換ならatofのが早くて楽な罠。 sscanfは使わないけど。。
924 :
デフォルトの名無しさん :2005/10/02(日) 18:06:18
大量にメモリを確保する予定がある場合、 配列で一気に確保するのと、ちまちま一つずつnewしていくのでは、どちらが確実なのでしょうか。 速さは問いません。 配列の方が無駄が無さそうですが、 素人目にはしかし、連続したメモリ空間が無いと失敗しちゃいそうなイメージがあります。
>>924 どっちかと言うと、ちまちま一つずつのほうが成功しやすいだろうな。
ページングの効く環境であれば、物理メモリの
フラグメンテーションによる危険性はほとんど無視できるんで、
あんまり差は無いと思うよ。
関係ないけどC++にとってatoiは標準ライブラリなの? 単に好みとしてC++の標準ライブラリだけを使いたくなるものジャン。 でもC++でatoiみたいなことするにはstrstreamに対して<<とか使うんでそ?めんどい
>>926 じゃあなんでstdネームスペースがあるんだよって言いたくなる
atoi The return value is 0 if the input cannot be converted to a value of that type. だれじゃこんな糞仕様にしたのは
ごめん
そんな時はstrtolですよ。
931 :
924 :2005/10/02(日) 18:58:41
>>925 用語を調べていたら遅くなってしまいすいません。
おかげでとても勉強になりました。ありがとうございました。
Cに由来する標準ライブラリ関数を残らず再設計してリプレースしてほしい
>>926 少なくともJIS X3014:2003では<c~>もその他のヘッダも全く同列に扱われている。
もっとも<c~>のほとんどはCの<~.h>と同じと書かれているが。
>>926 そんでもってstrstreamはほかとは別扱いで附属書D 互換性に載せられている。
そりゃあstrstreamはdeprecatedだからな
>>928 文句があるなら>930。
私ゃ妥当な仕様だと思うがね。
そういや、strstreamは使った事ないな。俺がC++始めた時には既に 標準規格が決まっていて、strstreamは使わないでください、みたいな 事が書いてあったな。でもこれを使ってるプログラムはたくさんあるわけで、 過去との互換性に残すんでしょ?
strstreamは規格化(?)されたときにすごく非難された、とは聞いたことがある。 んだからstrstreamを使ってるプログラムはほとんどないんじゃない?
>>926 はstringstreamを知った上でわざとstrstreamを出したのかな
>>938 ISO/IEC 1482:1998の通り、標準規格が決まったのは1998年の事で、C++自体は
1985年頃からあるわけで、その13年間でdeprecatedなプログラムが書かれた可能性
はどうかな?
あ、そうか、STLそのものは1993年にC++への組み込みが提案され、1994年に正式
に取り入れられる事が決まったので、たった4年ほどしかstd::strstreamを安心して
使える時期はなかったんだね。
>>910 その動作は10年前から知ってる。
…だからわざわざ絶対にまずい純粋仮想関数の場合と分けて
「微妙だ」と書いたんだが。
仮想関数がコンストラクタ内でだけは通常のようなオブジェクトの動的な型ではなく、
静的な型に従って呼び出されるというのは決して直感的に分かりやすい動作とは思えない。
(その呼び出しそのものは確かに動作として安全ではあっても、
その仮想関数からさらに仮想関数が呼ばれたりRTTIが利用されたりした場合の
動的な型と静的な型がどうなっているか考えると頭が痛くならないか?
多分このようにコンストラクタ内でだけ仮想関数の動作が「特別扱い」される仕様は
古いC++コードとの互換性のために残ってしまった仕様ではないかと思う。
そしてこの微妙な仕様のせいで純粋仮想関数をコンストラクタ内で呼ぶのは
呼ぶ相手がなくなるために具合が悪いわけだ。
純粋仮想関数のほうが歴史的には後でできた仕様だったからこうなったのだろうが。)
・・・なので絶対に必要なとき以外はやはり書かないに越したことはにと思うのだ。
(もっともその「絶対に必要な例」は中々思いつけないが。)
というわけで例に挙げたコードのように論理的には純粋仮想関数であるべきものを
コンパイルエラー回避目的でエラー例外を投げる仮想関数に書き換えるのは
決して必要に迫られて熟慮した結果というよりはやっぱり性質の悪い小手先の誤魔化しだと思う。
>>941 ・書かないに越したことはにと思うのだ→書かないに越したことはないと思うのだ
・決して必要に迫られて→ 必要に迫られて
>>901 >こういうコードはC++では実行結果が不定になる。
>(分かりやすく言うと書いちゃだめ。)
>仮想関数のセットアップはコンストラクタの実行の
>どの段階で行われるか規格は敢えて厳密には決めていないからだ。
>仮想関数をコンストラクタ中で呼び出すことはそもそも微妙だが、
>特に純粋仮想関数の場合は深刻で、結果は不定だと明示されている。
>気の利いたコンパイラなら上掲のコードについてエラーを報告するだろう。
・初心者も読むスレッドでこういう嘘を平気で書き、なおかつ指摘されても訂正もしない
・他人のミスとも言えないようなミスはことさらに(誤りを含んだ)長文で指摘する
・しかも多分スレ違い。
>>943 たぶん、得意げになりたかっただけだろ。
スルーで勘弁してやってくれ。
>>941 恥をかきたくなかったら、最低でも、規格書のどこを読めば
そんな動作をするか、リファレンス先を書いておけ。
ま、この場合完全な嘘だから、リファレンス先などありはしないがな。
>>941 D&E読め。
コンストラクタで仮想関数呼び出しでは派生クラスでオーバーライドしたほうの関数が呼ばれない理由がちゃんと書いてある。
ようするに派生クラスでオーバーライドした仮想関数の実装が
その派生クラスのコンストラクタが行われていることに依存していたら、
派生クラスのコンストラクタが呼ばれる前(== 基底クラスのコンストラクタの中)で、
派生クラスでオーバーライドされた仮想関数が呼ばれたらまずいことになる、
だからはコンストラクタでの仮想関数呼び出しでは派生クラスでオーバーライドした関数は呼ばれない仕様にしたと書いてある。
>>941 この動作がいかに(マシンにとって)自然であるか理解していないのなら、
10年もの間、誤解していたことになるな。
>>941 ワロスwwwwnwっうぇwuwwwrwuwっうぇwwpwwwwwow
952 :
デフォルトの名無しさん :2005/10/04(火) 03:31:20
晒し上げしていいの?
ドゾー
954 :
デフォルトの名無しさん :
2005/10/04(火) 11:12:11 ここまで説得力の無い長文の言い逃れは久々に見たw