1 :
デフォルトの名無しさん :
2001/01/22(月) 23:54 v(^・^)v
2 :
デフォルトの名無しさん :2001/01/22(月) 23:57
あげとくのv(^・^)v
3 :
デフォルトの名無しさん :2001/01/23(火) 00:08
CやめてC++に移ることのメリットとデメリットを教えてv(^・^)v
4 :
デフォルトの名無しさん :2001/01/23(火) 00:11
C/C++って書いたらハッカーを名乗る人に怒られました どうしてですか?
5 :
デフォルトの名無しさん :2001/01/23(火) 00:18
>>4 そいつ、「ハッカー」じゃなくて「バッカー」じゃなかったですか?
もしかしたら、プロブラマかもしれません。
そのひといわく CとC++は別のものだから一緒にしちゃだめだよ〜(笑 キミ、もっとべんきょうしたほうがいいよ いまどきC/C++なんて書いてるようじゃだめだめだね。 ということだそうです。 「別だから」って意味不明です。
7 :
デフォルトの名無しさん :2001/01/23(火) 00:42
|C/C++って書いたらハッカーを名乗る人に怒られました |どうしてですか? ザーメンがたまってむしゃくしゃしていたんだよ。 そーゆーもんよ
8 :
デフォルトの名無しさん :2001/01/23(火) 00:58
C++でPerlなどのようなパターンマッチをしてくれる関数は無いんですか?
9 :
デフォルトの名無しさん :2001/01/23(火) 01:07
>>6 >いまどきC/C++なんて書いてるようじゃだめだめだね。
時代は関係無いぜ。
そいつだってC++でCのライブラリ使ってんだろ?
コンパイラはC/C++両用だろ?
違うなら「別」でいいけど、氏んで欲しいナ!>バッカー
>>8 Perlよく知らんのだけど、正規表現とか?lexとかじゃダメ?
10 :
デフォルトの名無しさん :2001/01/23(火) 01:09
class A { public: class B { public: void Set(const A& a); private: int m_nCnt; } private: int m_nNum; }; で void A::B::Set(const A& a) { m_nCnt = a.m_nNum; } がコンパイルエラーになります。 コンパイラは「A::m_nNumにアクセスできないよ」 といいます。 そういうものなのでしょうか?
11 :
10 :2001/01/23(火) 01:11
あらら、インデントがなくなってる・・・ 見づらくてごめんなさい。
12 :
>10 :2001/01/23(火) 01:13
privateだし。 publicにしちゃだめなの?
13 :
10 :2001/01/23(火) 01:21
>>12 publicしてもいいんですが
せっかくクラスをネストさせてるのに
アクセスできないんじゃさみしぃなぁとおもったので。
イテレータっぽいの書いてたんですけど
イテレータって、どうしてもコンテナの内部にアクセスしなきゃ
ならなくて、
なるべく公開するもの少なくしようとしてクラス(この場合イテレータ)を
ネストさせたんですが、上のようなエラーが無常にも出てしまったんです。
ネストしたクラスの特権(特徴)ってあんまりないんですかね??
14 :
デフォルトの名無しさん :2001/01/23(火) 01:55
MFC的 #define offsetof(s,m) (size_t)&(((s *)0)->m) class A { public: class B { public: void Set(); private: int m_nCnt; } m_xB; friend class B; private: int m_nNum; }; void A::B::Set() { A* pThis = ((A*)((char*)this - offsetof(A, m_xB))); m_nCnt = pThis->m_nNum; }
15 :
10 :2001/01/23(火) 02:16
MFCってなんかすごそう。。。 ヌルポインタから->伸ばすあたりはドキドキものですね。。。 ところで friend class B; ならば、そこまでトリッキーにならなくてもいいんじゃないかと・・・ (というか、pThisがどこをアクセスしているのか良く分かりません・・・)
16 :
デフォルトの名無しさん :2001/01/23(火) 02:32
>>15 同じこと思いました。
>>10 のclass Aの中にfriend B;を加えれば全て解決です。
friend は誤解されることが多いのですが、これは安全のためにあるのですよ。
隠蔽度を高くするためにあるのです。
public な A::GetNum() const; を作るほうがはるかに危険だから、
firend を使うわけですよ。
class A に public インターフェースで m_nCnt を変更する メソッドをつけるのはためしました? ネストしたクラスっていうのは書いたこと無いんでわからないんだけど
19 :
10 :2001/01/23(火) 02:41
>>16 friendは安全のためなのですか。
そうだったのですか・・・了解です。
「friendは悪」と思っていたので
friend使わないで良い方法を探していたのですが
(それでネストしたクラスとか試してたんですが)、
friend使うことにします。
20 :
10 :2001/01/23(火) 02:44
>>17 ありがとうございます。
とりあえずfriend使う方針で逝きます。
ネストしたクラスについても知りたかったのですが、
もうすこし自分で調べてみます。
では。。。
21 :
デフォルトの名無しさん :2001/01/23(火) 03:02
C++とJavaを較べると将来生き残ってそうなのはどちらですか?
22 :
初心者 :2001/01/23(火) 03:29
2つ疑問があるのですが VC++6でDOS画面での実行結果がすぐに閉じてしまう。 あと、コマンドライン引数を打ち込むことができない。 よかったらおしえていただけますか。
23 :
>22 :2001/01/23(火) 03:36
[プロジェクト]-[設定]-[デバック]-[プログラムの引数] で設定できると思う。
24 :
>22 :2001/01/23(火) 03:45
>VC++6でDOS画面での実行結果がすぐに閉じてしまう。 !ボタンなら閉じないと思う。 それか、main()の最後に、_getch()とでも書いておく。
25 :
初心者 :2001/01/23(火) 04:04
>23 ほお。 >24 なるほど。 ずっとCの勉強はLSIC86でやってたんでなれてないです。 また疑問があったら質問しにきます。 ほんとにありがとうございました。
26 :
デフォルトの名無しさん :2001/01/23(火) 20:59
CLASS B{ B(); ~B(); AA* aa; } CLASS A:public AA{ A(); ~A(); B b; } という二つのクラスがあったとき b.aaにAのthisポインタを渡したいんですけど、 AのコンストラクタではthisはNULLでした。 thisはコンストラクタが動いた後からしか使えないんでしょうか?
27 :
デフォルトの名無しさん :2001/01/23(火) 21:19
>thisはコンストラクタが動いた後からしか使えないんでしょうか? そんなことは無い。
>>26 class B
{
private:
AA *aa;
public:
B(AA &);
};
B::B(AA &a)
: aa(&a)
{
}
class A : public AA
{
private:
B b;
public:
A();
};
A::A()
: b(*this)
{
}
こういうことをしたいのでしょうか?
>>19 >「friendは悪」と思っていたので
>friend使わないで良い方法を探していたのですが
gotoと同じで、無闇に使うのは悪です。
friendを使わなくてもいいのに済むならそのほうがいいですし、
上手く使うにはある程度の技量が必要です。
しかしこの例の場合のように、明らかに friend を
使ったほうが安全な場合もあるため、
無闇に嫌うのもまた問題があるのです。
29 :
26 :2001/01/23(火) 23:02
>>28 ごめんなさい
A::A()
: b(*this)
{
}
みたいなのがちょっと良くわかんないので勉強してきます。
簡単にいうと、
AAは既製のクラスなんですが、
一部機能がわかりにくいので使いやすくまとめたクラスがBなんですが
やっぱり機能を使うには
aa->〜〜()
みたいにAAクラスのポインタを使ってるんです(^^;
単に馬鹿なだけでしょうか(^^;
30 :
ひげ :2001/01/23(火) 23:18
>>29 これをコンパイル実行してみてください。
この方法は「初期化」と呼ばれる方法です。
「代入」と同じ効果を生むのですが、厳密には異なります。
(たとえば、メンバフィールドが const 変数であった場合など)
詳しい議論は『Effective C++』の第12項を参照すると良いと思います。
// 実行結果
// 777
#include <iostream>
using namespace std;
class Test
{
public:
int number;
Test();
};
Test::Test() : number(777)
{
}
int main()
{
Test t;
cout << t.number << endl;
}
31 :
デフォルトの名無しさん :2001/01/23(火) 23:29
>29 A::A():b(*this)は、 Aのメンバ変数bを、thisポインタが参照しているインスタンスの値 (つまり自分自身の値)を引数とするコンストラクタを起動して 初期化する、っていう意味だよん。 class BB{ private: AA* aa; public: void hage(){aa->hoge();} } とやるのは、オブジェクト指向の委譲の考え方。別に変じゃないよ。 ただ、そもそもclass Aとclass Bが相互参照している必要があるの かどうかをチェックしてある?
32 :
26 :2001/01/23(火) 23:37
>>28 申し訳ない、どあほうでした
単にクラスAが準備出来てないタイミングで
機能使おうとしてただけでした・・・・
鬱だ・・・・
>>30 >>31 たった今調べ終わったとこでした
解説ありがとうございました。
簡単に言うとMFCでCView(AAクラス)のスクロール関数を
外(Bクラス)にまとめただけです(^^;
AクラスがCViewの派生クラスで、いろいろと使いまわせないかなぁと(^^;
33 :
デフォルトの名無しさん :2001/01/24(水) 00:16
>32 最近Javaしかやってないので、間違ってると思うが 一応FactoryMethodパターンをどうぞ。 詳しい人突っ込みよろしく。 class B{ public: static const int TYPE_AA; static const int TYPE_A; private: AA* aa; setAA(AA* in){aa = in;} B(){} public: B~(){delete aa;} static B* create(int B){ B* instance = new B(); switch(B){ case TYPE_A: instance.setAA(new A()); break; case TYPE_AA: instance.setAA(new AA()); break; } return instance; } } //static変数初期化 static const int B::AA=0; static const int B::A=1; 使用法 B* bAA=B::create(B::AA);//AAのインスタンスをBに持たせたいとき B* bA=B::create(B::A); //AのインスタンスをBに持たせたいとき
34 :
デフォルトの名無しさん :2001/01/24(水) 00:17
間違った。 //static変数初期化 static const int B::TYPE_AA=0; static const int B::TYPE_A=1; 使用法 B* bAA=B::create(B::TYPE_AA);//AAのインスタンスをBに持たせたいとき B* bA=B::create(B::TYPE_A); //AのインスタンスをBに持たせたいとき
35 :
質問の名無しさん :2001/01/24(水) 00:31
ARMだったかプログラミング言語C++かなんかに書いてあったのですが、 「operator T()の定義は避けよう」と有ったのですが 理由がよくわかりません。やっぱり、あいまさの問題が出てくるからでしょうか?
36 :
デフォルトの名無しさん :2001/01/24(水) 01:18
operator T()?そんな定義できるなんて知らんかった。 デフォルトコンストラクタのテンプレート(になるのでしょうか?) なんか作ってどうするの?
>>36 いや、キャスト演算子だと思う。
避ける理由は良くわかんないですが、
僕は暗黙の型変換がどうも好きになれないので書かないようにしてます。
(明らかに便利&安全そうなものには書いちゃいますけど)
引数が1つだけのコンストラクタにはexplicit付けてます。
38 :
ミトコンドリ子 :2001/01/24(水) 10:12
>>35 36のいうとおり、キャスト演算子ね。
避ける理由は
「More Effective C++」,Scott Meyers,安村 通晃 他訳,アジソン・ウェストレイ,1998
ISBN4-7561-1853-4
項目5:ユーザ定義の変換関数に気をつける
を参照してちょうだい。
ちょう要約すると「基本的な問題は、このような関数がしばしばあなたが望みもしなければ
期待もしないようなときに呼ばれてしまうことにある。結果は正しくなくなることもあれば、
診断が気の狂うほど難しくなるような、直感的でないプログラムの振る舞いに
なることもある。」
39 :
デフォルトの名無しさん :2001/01/24(水) 17:17
wide characterを使った処理をしたいのですが、 wofstream に wchar_tで出力しても、ofstreamにcharで出力しても 結果がまったく変わりません。バイナリモードでファイルを開いても だめです。例えば、L'A'を出力したときに、0x4100がファイルに 入っていればいいんですけど。 この厨房をお助けください。
40 :
デフォルトの名無しさん :2001/01/24(水) 17:23
すいません。39です。処理系を書くべきでした。 環境はWindowsNT4でVC6です。ただ、質問がVC関係ではないので ここを選ばせてもらいました。よろしくおねがいします。
41 :
名無しさん@@ :2001/01/24(水) 17:44
>>39 うん、だから入出力時にマルチに変換してる。
ライブラリの問題以前に規格やフォントの問題もあるし。
linuxだとwctomb関数がマニュアルにある。
(マルチスレッド云々と状態の切り替えの話に注意して読んで)
みんなC++を使うのだage
43 :
デフォルトの名無しさん :2001/01/28(日) 01:55
DOSの16bitの環境で動作するANSI C++に追従してる処理系ってあります? DJGPPみたいに、DPMI上で動く様なのは除外してください。 つまり80186で動く様な物です。 テンプレートはでかくなるので無くても良いですが。 (すると、ライブラリの大半が使えない?) 「例外」程度は使いたいです。
44 :
デフォルトの名無しさん :2001/01/28(日) 02:26
BCC45
45 :
デフォルトの名無しさん :2001/01/28(日) 03:14
>>44 Borland処理系は4以降からDPMI使ってるみたいなのでだめです。
46 :
デフォルトの名無しさん :2001/01/28(日) 04:10
>>45 TC++1.0
一番初期のヤツね。ディスク3枚組みのヤツ。
正真正銘16BitDOSでC++。
80186オプションもちゃんとあるぞ。
>>46 43の「ANSI C++に追従している」という意味は、多分
RTTIやnamespaceや例外やテンプレートのような後発の仕様、
および STLその他現在の標準C++ライブラリをサポートしている
という意味だと思うが....俺は知りません。
しかしテンプレート使うとモノがでかくなりがちであり
pureなDOS環境ではちと厳しいのでは。
48 :
デフォルトの名無しさん :2001/01/28(日) 15:03
複数のクラスから使いたいサブルーチン(memcpy類似のアプリ固有 のよく使う処理)って、どういう名前空間に置きますか? アプリのメインのクラス内にpublicで置くと、そのクラスのインス タンスをexternするか、子クラスにポインタを渡していかなければ ならず、すっきりしません。 かといって大域に置くのも何かCくさくて嫌なのです。
49 :
デフォルトの名無しさん :2001/01/28(日) 15:08
singletonにすればー.
50 :
46 :2001/01/28(日) 16:10
>>47 43はテンプレート無しで良いっていってんじゃん。よく読め。
RTTIって使ってる奴いんの?その辺はどうだか知らん。
51 :
デフォルトの名無しさん :2001/01/28(日) 18:42
>>48 はstaticなメソッドを知らないらしい。
>>50 Embedded C++ だね、それ。
RTTI を使っているやつは存在する。
オブジェクト指向初心者は多重継承を下手に使って失敗する。
オブジェクト指向中級者は多重継承を嫌って使わない。
オブジェクト指向上級者は多重継承を上手く使って楽をする。
ちなみに俺は中級者。
52 :
デフォルトの名無しさん :2001/01/28(日) 20:01
ATL固有の話になってしまって申し訳ないのですが、 CWindowImpl<>::Create() ってオーバーライドしても平気なのでしょうか? オーバーライドする必要があるのですが、virtual宣言されていないので どうなってしまうのでしょうか。 実際に使ってみたところ問題なく使用できているのですが、 正しいのか間違いなのか、教えてください。
>>52 virtualをちゃんと勉強しよう。
ライブラリ的には問題ないと思う(信じたい)けど、
52の使い方次第。
virtual宣言すると、派生元のクラスのポインタで呼んでも、
派生クラスで生成してれば派生クラスのメンバ関数が呼ばれる。
(デストラクタだとちょっと違うが)
54 :
デフォルトの名無しさん :2001/01/28(日) 21:27
オーナードローボタンクラスを作ってたのですが、 生成するたびにBS_OWNERDRAWを指定させるのもなんだかな、って思ったので、 CreateをオーバーライドしてBS_OWNERDRAWをしていしてから CWindowImpl<>::Create()に渡しているのですが、 この場合問題なさそうですね。 >virtual宣言すると、派生元のクラスのポインタで呼んでも、 >派生クラスで生成してれば派生クラスのメンバ関数が呼ばれる。 これはわかっていましたが、オーバーライドさせるときは無条件で virtualと思ってたので、質問しました。 やっぱりプログラミング言語C++買うべきですね。 あれってCと違ってべらぼうに高いんですが(^^;
55 :
デフォルトの名無しさん :2001/01/28(日) 21:36
高いのは理解できなくなもないが、 分厚くてでかいのがきつい。 持ち運び不便。
56 :
55 :2001/01/28(日) 21:37
1行目 なくな→なく
おいら、多重継承は前まで絶対しないことにしてたんだけど、 Javaを覚えてからは、C++で多重継承するときは必ず片側は 完全抽象クラスのみにするようになった。 関数実装の多重継承は禁止。これで安心。僕って上級者???
58 :
43 :2001/01/28(日) 23:46
ボーランドサイトでTurboC++1.01が見つかりましたので、これで我慢します。 ちなみに例外は使えない様です。4.0からかな? ついでですが、RTTIや名前空間とかは使わないです。>47 #C++はもっとCみたいにコンパクトな言語にならないですかね。
59 :
43 :2001/01/29(月) 00:02
いままでわたしはCでOO風に書いてきました。 CでOO風に書く利点としては、Cさえ動けばどんな環境でも使える事ぐらいですが、こういう事やってる(やってた)人います? 不便な点は、Cではinlineキーワードが標準で使えないから、アクセサの効率を上げる為に、処理系毎に__inlineだの、static __inline__だのをマクロ定義しなきゃいけないとか、色々面倒が多いですが。 それと、他人にソースを渡す場合は困りますね。 いちいち書き方の説明する様な事をしなくちゃいけないんで。 そういう時はC++でラップして渡しています。(二度手間ですが)
60 :
デフォルトの名無しさん :2001/01/29(月) 00:18
RTTIって何に使うの?用途が思い浮かばない。デバッグ?
61 :
名無しさん@Emacs :2001/01/29(月) 00:20
callback してきたオブジェクトをいつ delete するか悩んでいます. 例えば... class B { public: B(A* a) { a->onCallBack(); } }; class A { public: B* createB() { return new B(this); } void onCallBack(); }; とかなってる場合, B のインスタンスはいつ delete すればよいですか? A::onCallBack() に B* を乗せて void onCallBack(B* b) { delete b; } とかするのはだめですよね. つまり, callback 後は必要ないオブジェクトの破棄をいつ行うか? ということなんですが, いい方法あるでしょうか?
>59 多分CでOO風に書くって、1ファイル1クラスに見立てて、ファイルスコープ のグローバル変数をインスタンス変数に見立てて、そのファイルの関数を 唯一のそのグローバル変数へのアクセス手段にするようにするとかだよね。 CでOO風に書いても、クラスとインスタンスの関係は実現できないので ポリモルフィズムが表現できないと思うんだけど、其の辺は無視? 単なる概念モジュールの階層構造化を指してOOと呼んでるのでしょうか? >60 ポリモーフィズムの意義を勉強せよ。
>61 よう分からんが、Bのインスタンスはスマートポインタで ラップして値で持ちまわるようにしたら?
64 :
60 :2001/01/29(月) 00:46
>>62 RTTIでポリモフィズムとなると、
typeid演算子を使って、実際のクラスを判別するんですか?
かえっておかしなことになるような。
なんか勘違いしてます?
65 :
43 :2001/01/29(月) 01:25
>>62 グローバル変数は一切使いません。
インスタンスはスタック、またはヒープに確保します。
シングルトンパターンの実装やリソースカウンタなどはstaticな変数を使いますが。
多態が必要な場合、typeid(実はenumやint)と関数のポインタテーブルを使って実装します。(かなり面倒ですが。)
66 :
ミトコンドリ子 :2001/01/29(月) 09:54
>>60 RTTIはtypeidよりはdynamic_castでよく使うんじゃないかしら。
用途としては、抽象クラスのポインタ(参照)しかとれない場合(たとえば
抽象クラスのポインタのコンテナをイテレートするとき)に、なんらか
(派生クラスでしか定義されていないメンバを呼びたいとか)の理由で
ダウンキャストしなくちゃいけないときが一番多いかしら。
なるべく使いたくないけど、compositeパターンなんかを使うと
ある程度は使わざるをえなくなることが多いわ...
なるべくdynamic_castを使わずにすむように心がけながら設計
してるけどね。
67 :
ミトコンドリ子 :2001/01/29(月) 10:01
>>61 まず所有関係に注意しながら設計を見直すのが最初だと思うわ。多くの場合は
きちんと考えれば、どのインスタンスをいつ破棄すれば良いかは明確にできると
思うけど。
それが難しい場合(スレッド間で受け渡しするインスタンスなど)は、63の言うとおり
何らかのスマートポインタを使うのがいいんじゃないかしら。
でもうまく使わないとバグの温床になるわよ。気をつけてね。
わかったからそのネカマ言葉をやめてくれ
>67 C++を知らない奴が、スマートポインタに関数内のローカル変数の アドレス渡して、その後原因不明で落ちる!と大騒ぎするのを 多々目撃しております。
70 :
60 :2001/01/29(月) 11:48
>>66 RTTIってdynamic_castも含めるのね。dynamic_castなら使っていますので解かります。
てっきりRTTI=typeidで得るclass type_infoのことかと思い込んでいました。
親切な回答ありがとうございました。
では改めて質問。
typeid演算子、ならびにclass type_infoって何に使っていますか?
デバッグ用機能です
72 :
ミトコンドリ子 :2001/01/29(月) 12:55
>>69 やりがちよね。
class Foo {
protected:
Foo();
public:
virtual ~Foo();
public:
static SmartPointer<Foo> create();
};
みたいにして、スマートポインタの使用を強制するようにしてるわ。
>>70 めったに使わないわ。おもにassertで使うわね。
派生クラスじゃなくて、ぜったい特定のクラスのインスタンスが
欲しいときとかに assert( typeid(*ptr)==typeid(Foo) );とか。
73 :
デフォルトの名無しさん :2001/01/29(月) 14:45
ミリ秒間、何かの処理をさせるみたいな時に使う時間をはかるもの タイマーって言うんでしょうか? そういったタイマーで、一般的に使われる関数を教えて下さい
74 :
SAGE :2001/01/29(月) 14:56
winapi -> SetTimer()
精度が必要ならマルチメディアタイマー
77 :
61 :2001/01/29(月) 21:02
>>63 B を作るオブジェクトは最後まで死なないので
スマートポインタは使えなさそうな気がします.
なんか間違ってるかな.
>>67 設計見直しですか.
いや, そんな気はしてんだよなぁ.
もちっと考えてみます.
2人ともありがとっ
78 :
73 :2001/01/29(月) 22:07
なるほど ありがと、74・75・76
79 :
age :2001/02/15(木) 04:19
class A { public: A(); private: const int m_data[10]; }; で、class AのコンストラクタA::A()を書こうとして困ってしまいました。 A::m_data[10]の初期化はどのように書けば良いのでしょうか? constにしているのは困っているところを強調するためなのでご了承ください。 メンバ配列の初期化ってムリなんですかね・・・
>>79 さん
const を外して
A::A(){
for( int i=0; i<10; i++)
m_data[i] = i;
}
です。
・・・だと思います・・・自信なし・・・。
81 :
80 :2001/02/15(木) 06:35
あああ〜〜〜〜 やっぱし違うと思います。すいません。無視してください。
A() { int i; int * p = (int *)m_data; for( i = 0; i < 10; i++ ) p[i] = 0; } こんなんど?
83 :
79 :2001/02/16(金) 01:31
>>80 ,82
質問のしかたがまずかったかもしれません。
やりたいこととしては
A::A()
: m_data(????)
{
//ここには書きたくないのです・・・
}
のように初期化列の中に配列の初期化を書きたいなぁと思ったのです。
普通のメンバ変数だったら
class B
{
public:
B() : m_data(0) {}
private:
const int m_data;
};
みたいに書けるのに、配列はどう書けばよいのやら・・・
どうあがいてもムリ??
配列はできないような…?std::vectorじゃだめ?
85 :
79 :2001/02/16(金) 03:43
>>84 std::vectorほどの柔軟性は必要なかったりしてるんです。
動的にメモリ確保されても困るので・・・
具体的には今3Dのプログラム組もうとしていて、
4次元ベクトルのクラスとか作ろうとしたとき
struct Vector
{
Vector(float x, float y, float z, float w);
float m_data[4];
};
てな具合にしたのですが
m_data[4]の初期化で困ってしまったということでした。
やっぱり配列はどうしようもないようですね。
あきらめて80,82さんのようにコンストラクタの{}中に書きます。
ありがとうございました。
つうか、配列でそんな書き方できるほうが危ないんだよ。 もうすこし勉強しないとわからんかもしれんが。
最近、vectorやlistを独自の使ってるのを見ると、 素直にSTL使ってくれって思うぜー。 メモリは先に必要な分だけ確保しておけば問題ないぜー。
88 :
デフォルトの名無しさん :2001/02/16(金) 09:53
初期化列の中に、初期化する変数書く利点ってなんだ? 配列は初期化できないし…?
89 :
デフォルトの名無しさん :2001/02/16(金) 12:13
利点というよりそこに書かなきゃならない場合があるだけです。 逆に言えば初期化列に記述できないものはそもそも初期化列 で初期化する必要がないという事。 つまり今回の例は「ここに書きたくない」なんてゴネてないで素直に {}に書けつーことです。
90 :
デフォルトの名無しさん :2001/02/16(金) 12:15
デバッグ用に内部データがデバッガで見やすくかつ鬼のように チェックの厳しいSTLの実装ってどこかにない?
92 :
デフォルトの名無しさん :2001/02/16(金) 13:21
>>89 利点というよりそこに書かなきゃならない場合
ってのはどういう場合なのん?
デフォルト以外で初期化したい基底クラスや デフォルトコンストラクタを持たないオブジェクト、 参照やconstオブジェクト、 効率のためデフォルトの初期化を行ないたくない場合とか その他いろいろあるっしょ
94 :
わざわざすまんのお :2001/02/16(金) 15:03
{ } 内では、できない初期化があるってことなのか…。
95 :
デフォルトの名無しさん :2001/02/16(金) 16:50
配列自体を病める方に一票。
96 :
デフォルトの名無しさん :2001/02/16(金) 16:55
Cでは struct ta sub() { struct ta a; return a; } は禁じ手ですが(autoのstructを返すため) C++では CString xxxxx() という関数がいっぱいあるのはなぜでしょう? C++ではクラスのリターン値は保証されるのですか?
97 :
デフォルトの名無しさん :2001/02/16(金) 18:14
>>96 C++でもauto領域のリターンは御法度だ
ソースはみたか?
CString xxxx()のなかでauto変数領域返してるか?
98 :
デフォルトの名無しさん :2001/02/16(金) 18:48
御法度じゃないぞ。代入コンストラクタって言葉知ってるか?
returnで代入コンストラクタが働くって意味かい?
100 :
98じゃないけど :2001/02/16(金) 19:01
>returnで代入コンストラクタが働くって意味かい? そうよ。 AnyClass obj; obj = anyFunc(なんかの引数); とかで、anyFuncがAnyClassのautoオブジェクトをreturnしてたら、 1.AnyClass::AnyClass(const AnyClass&)でリターン用臨時オブジェクトが作られる。 2.AnyClass::operator=(const AnyClass&)で臨時オブジェクトがobjへコピーされる。 3.臨時オブジェクト消滅 てなことが舞台裏で行われるのです。 処理系の実装によっては、もちょっと最適化されるかも知れんけど。
101 :
100 :2001/02/16(金) 19:05
でも、96みたいなのも近頃のCでは 御法度じゃなかったんじゃない? struct ta* func() { struct ta taObj; return &ta } は、おもくそまずいけど。
102 :
100 :2001/02/16(金) 19:06
ちがった、 struct ta* func() { struct ta taObj; return &taObj; } だ。
103 :
デフォルトの名無しさん :2001/02/16(金) 19:07
ちなみに AnyClass obj = anyFunc(なんかの引数) ってやったらどうなるか考えると面白いぞ
104 :
いさましいチビの女 :2001/02/16(金) 19:57
>>96 101も言ってるけど、それが禁じ手なんて初めて訊いたよ。
どこのダレがどういう理由で禁じ手にしてるか教えてくれ。
105 :
デフォルトの名無しさん :2001/02/16(金) 20:08
コピコンちゃんとつくるの忘れてるくせに
オブジェクトリターンかましたあほが広めてるんじゃないの?
>>104
106 :
デフォルトの名無しさん :2001/02/16(金) 20:15
おそらく, ・構造体はでかいからポインタでやりとりしたほうがいい ・autoなオブジェクトへの参照を返してはいけない が,どこをどう勘違いされたのか ・autoな構造体オブジェクトは参照でかえせないから, リターンしてはいけない と勘違いされたんじゃないかな。C言語でもautoオブジェクト を値で返す分には支障はないよ。 原理がわかってないとこういう勘違いが起こるんだろうね。
107 :
デフォルトの名無しさん :2001/02/16(金) 20:16
>>105 ありそうだな。でも96は、
「Cでは…は禁じ手ですが…」
と言ってんだよね。
うぇーん、C++なんかきらいだー  ̄ ̄ ̄∨ ̄ ̄ ̄ ̄ ̄ ̄ ∩_∩ ( ´Д⊂ヽ ⊂ ノ 人 Y し (_)
109 :
105 :2001/02/16(金) 23:24
>>107 む、確かに。
101、102!
余計な口挟むんじゃねぇ!C厨房ゴルァ!
なんつってな、無視したんだよ、虫。
110 :
105 :2001/02/16(金) 23:34
番号間違えた。 よって意味不明。 逝ってきま〜す。
111 :
79 :2001/02/16(金) 23:34
もりあがってるところ申し訳ないのですが、
>>93 constなメンバ変数の初期化は初期化列に書くしかないわけですよね。
で、僕が最初に質問してたんですが、
class A
{
public:
A();
private:
const int m_data[10];
};
みたいな作りにしなきゃいけないってことになっら
A::m_data[10]はどのように初期化すればよいのでしょう?
>>82 みたいに強引にやるしかないんですかね。。。
初期化のときだけconst_castしたら?
113 :
79 :2001/02/16(金) 23:49
そうですね・・・あきらめます。 あぁ、どうも配列だけC++の中で異質な感じがする今日この頃。。。
114 :
部外者A :2001/02/16(金) 23:49
96の言い分も少しは正しい。(かった?) まず、昔のCコンパイラは構造体の(ポインタではなく)インスタンスを返せない物があるって事。 返せても特別な領域(strtokと同じ様な場所)に一旦コピーするものもあったから、そういう処理系ではスレッドセーフにもできなかった。 よって、そういった処理系での互換性をも保とうとしているプログラマから見れば、構造体を返却値に持つ関数を定義する事は「禁じ手」であると言える。 現在のANSI-Cに準拠する処理系でのみ動作を期待するプログラムならば、スタックにコピーするので問題ない。 こんなんでどう?>96,その他
115 :
デフォルトの名無しさん :2001/02/16(金) 23:52
>113 まあねー。クリティカルセクションじゃなけりゃSTL使うわな。
116 :
106 :2001/02/17(土) 01:43
>>114 まぁ,確かに。
>>113 ,(111,79)
うーん,要素数をテンプレート引数に取るテンプレートな
スマートアレイじゃだめなの?
117 :
デフォルトの名無しさん :2001/02/17(土) 01:46
const配列メンバはstaticじゃなきゃ。 よって、素直にクラス使っとけ。
118 :
>113 :2001/02/17(土) 03:02
クラス内のconstは実装部で宣言して初期化もそこでする。 effective c++、ずばり一章。 class aaa{ public: static const int const bbb[10]; void showprivate(void) { for(int i=0;i<10;i++) cout << ccc[i] << ":"; } private: static const int const ccc[10]; }; const int const aaa::bbb[]={0,1,2,3,4,5,6,7,8,9}; const int const aaa::ccc[]={10,11,12,13,14,15,16,17,18,19}; int main(int argc, char* argv[]) { for(int i=0;i<10;i++) cout << aaa::bbb[i] << ":"; cout << endl; aaa c; c.showprivate(); cout << endl; return 0; }
119 :
79 :2001/02/17(土) 03:29
>>116 template <class T, size_t N>
struct CArray { T m_data[N]; };
みたいな感じのを配列の代わりに使えってことでしょうか?
んんん、、、問題を先送りにしている感じがしないでもないですが
改善になるのかな?
class A
{
public:
A(const CArray<int,10>& data)
: m_data(data)
{}
private:
const CArray<int,10> m_data;
};
で無事constな配列の初期化ができました(なのかな???)
>>117 >>118 staticなconstの配列だったら悩まなくてもokですね。
でも今回の場合staticではないconstな配列の初期化で悩んでたので・・・
>>115 思う存分STLが使える開発っていうのも一度やってみたいです。。。
(でもきっとSTLの実装が気になって思う存分使えないんだろうなぁ>自分)
120 :
106=116 :2001/02/17(土) 04:09
>>119 そうそう,そういうの。メモリ上の配置も素の配列と変わらないから
いけると思うんだけど。
そこまで初期化式にこだわる理由がわからない・・・
122 :
79 :2001/02/17(土) 04:39
>>120 たしかにCArrayのコピーコンストラクタで初期化できるようになったのは
改善だと思うのですが、class A に
A::A(int a0, int a1, int a2, int a3, int a4,
int a5, int a6, int a7, int a8, int a9)
みたいなコンストラクタも欲しいなぁとなると、またconst_castの
お世話になってしまいますよね・・・
CArrayの初期化の方法が、コピーコンストラクタと配列の初期化の
方法しかないからしょうがないんですけど・・・
まあ、あまりダダをこねないで、
配列と仲良くやっていこうと思ったのでした。
123 :
79 :2001/02/17(土) 04:41
>>121 気になるとこだわってしまう性格でして・・・すみませんでした。
124 :
106=116 :2001/02/17(土) 04:42
>そこまで初期化式にこだわる理由がわからない・・・ 79氏は,リアルタイム処理やゲームプログラミングをなさってるんじゃないかな? 初期化式で初期化すれば,デフォルトのメンバ初期化をスキップできて 効率がいいし,STLを使わないのも,メモリ領域を静的にとりたいのか,もしくは 開発環境が組み込み用とかでSTL自体が整備されてない環境とか?
125 :
デフォルトの名無しさん :2001/02/17(土) 05:27
<stdio.h> ってスタンダードアイオーヘッダーって読みますよね。 今日学校の教師に <string.h> の読み方を 「スタンダードリングヘッダー」って教わりました。 これって「ストリング」って読むんじゃ無いですか? 自分は間違いだと確信有るんですが。 それと教師に指摘してあげるべきだったでしょうか。
126 :
79 :2001/02/17(土) 05:30
>79氏は,リアルタイム処理やゲームプログラミングをなさってるんじゃないかな? むむむ、、、なんか書きこみにクセとかありました?? んーとりあえず退散します。ありがとうございました。
>>125 stdio.h ... スタジオ・ヘッダー
と読んでいました。学生の頃。
というか、C的話題?
>>125 そういうのは、わかっていても言わないの。
129 :
96 :2001/02/17(土) 14:53
みなさんありがとうございました。そしてごめんなさい。 Cの所は引き合いに出すために適当に書いてしまいました。 101さんのようなことはまずいと言いたかったのです。 知りたかったのはCStringの戻り値のみなので 理解できました。 もっと勉強します。
130 :
デフォルトの名無しさん :2001/02/17(土) 23:45
質問なのですが
http://demo.and.or.jp/makedemo/mini_class/file_search/index.html にあるソースをbcc5.5.1でコンパイルしたのですが
エラー E2285 'output_filename::operator () <_NAME,_MORE_INFO>(string,_WIN32_FIND_DATAA)' に一致するものが見つからない(関数 search_file<string,output_filename>(string,string,const bool,output_filename &) )
*** 1 errors in Compile ***
というエラーが出て困ってます。どうすれば回避出来るのでしょうか?
ネタなんだろうけど・・・ #include <windows.h> って行は先頭辺りにある?>130
あ、#endifが無い様だね。そのソースとヘッダもう一度よく見てみると良いよ・・・>130
133 :
デフォルトの名無しさん :2001/02/18(日) 01:48
>131、>132 #include <windows.h>はあります。 #endifもエラーで出たのですぐに書き加えました。 それでもやっぱりエラーになるんですよね。 なぜなんでしょうか?記述ミスがまだあるんでしょうか?
134 :
ミトコンドリ子 :2001/02/18(日) 03:08
>>130 テンプレートメンバ関数は、コンパイラによっては正確にコンパイルできないことが
多かったわ。
テンプレートメンバ関数を無くして書き直してみたらどう?
動けばメンバテンプレート周りのコンパイラのバグ。
動かなければその他の原因ね。
#この程度の機能をテンプレートメンバにする必要性は感じないけどね。
135 :
130 :2001/02/18(日) 03:26
>>134 それはもう既にやってみたんですが、一応ちゃんと動きました。
やはりbccのバグなんでしょうか?
バグならあきらめるしかないですね・・・。
136 :
ミトコンドリ子 :2001/02/18(日) 03:32
>>135 バグだと思うわよ。
短いコードでバグが出せるなら、サポートに送っておくといいわ。
次のバージョンで直る「かも」しれないしね。
あとは
・テンプレート引数の数を減らす
・テンプレート引数を明示する
とかして、コンパイラが探索しなくちゃいけない範囲を限定してあげると
通ったりすることもあるわよ。でも不毛な努力になることが多いから
お勧めはしないわ。
137 :
130 :2001/02/18(日) 03:40
>>136 わかりました。出来たらサポートに送ってみようと思います。
不毛な努力の方も試してみます。
ありがとうございました。
138 :
デフォルトの名無しさん :2001/02/18(日) 05:07
>>130 テンプレートメンバ関数の引数をconstにするとうまくいったよ。
template<class _NAME, class _MORE_INFO>
void operator()(_NAME &filename, _MORE_INFO &info)
を
template<class _NAME, class _MORE_INFO>
void operator()(const _NAME &filename, const _MORE_INFO &info)
でどう?
ちなみにこれはテンプレートメンバ関数が原因ではないかも。
下のコードでも同様なエラーになります。
template <class T>
T add(T& lhs, T& rhs)
{
return lhs + rhs;
}
int main()
{
return add(1, 2);
}
これも同様に引数にconstを付けるとokになります。
この動作って、bcc固有? C++の仕様?
手元にあるコンパイラがbccしかないので確認のしようがない・・・
どなたかhelp・・・
139 :
130 :2001/02/18(日) 06:26
>>138 おお!const付けると上手く行きました。ありがとうございます。
自分もbccしか使ってないので
VCとかで確かめられないのがつらいです。
140 :
デフォルトの名無しさん :2001/02/18(日) 08:50
VC++ ではconst無しでも通るみたいっす。
>>138 -139
141 :
デフォルトの名無しさん :2001/02/18(日) 14:40
質問です。レベル低くてすいません。 ファイルポインタをファイルの先頭に移動するために ifstream::seekg() を使用しましたが、うまくいきません。 ifstream ifs("filename"); <-- 読みこみ処理 --> ifs.seekg(0, ios::beg); // <- ポインタを先頭に <-- 読みこみ処理。でも読めない… 間違ってますか?
142 :
デフォルトの名無しさん :2001/02/18(日) 15:23
>>138 C++の仕様上、非const参照の初期値は左辺値でなければならない。
だからエラーになるのが正しいと思う。
エラーにならないコンパイラは古いソースとの互換性を
考慮してるのではないかな。
143 :
138 :2001/02/18(日) 15:49
>>142 なるほど。
>>138 の add(1,2) の「1」とか「2」は
左辺値ではないですね(右辺値?)
>>130 の例では、filesrc.hの65行目の
op(strCurrentFolder+"\\"+FindData.cFileName, FindData);
の第1引数「strCurrentFolder+"\\"+FindData.cFileName」が
左辺値ではないんですね。
侮りがたし>bcc
144 :
106 :2001/02/18(日) 16:47
>>141 オープンには成功しているわけですね。
お使いの処理系は? C++の規格だと,ios::begじゃなくて
iso_base::begですよ。古いヘッダを使ってるとか?
145 :
144=106 :2001/02/18(日) 16:49
あ,ごめんなさい。タイプミスです。 iso_base::beg ↓ ios_base::beg
146 :
106 :2001/02/18(日) 18:51
>>79 効率はどうでもいいなら,こんなのはどうですか?
#include <iostream>
#include <cstdarg>
#include <cstddef>
#include <algorithm>
using namespace std;
template<class T, size_t sz> class Array {
T buff[ sz ];
public :
Array() {}
Array( size_t n, ... ) {
va_list ap;
va_start( ap, n );
for( size_t i = 0, lim = min( sz, n ); i < lim; i++ ) buff[i] = va_arg( ap, T );
va_end( ap );
}
template<class T2, size_t sz2> Array( const Array<T2, sz2> & a ) {
size_t lim = min( sz, sz2 );
for( size_t i = 0, lim = min( sz, sz2 ); i < lim; i++ ) buff[i] = a[i];
// sz < sz2 の場合は例外を投げても良いかもしれない
}
// コピーコンストラクタとコピー代入演算子はデフォルトで十分
T& operator[]( size_t i ) { return buff[i]; }
const T& operator[]( size_t i ) const { return buff[i]; }
// 添え字範囲が範囲外なら例外を投げるat()を定義しても良いかもしれない
operator T*() { return &(buff[0]); }
operator const T*() const { return &(buff[0]); }
};
template<class T, size_t sz>
Array<T, sz> AIL( T first, ... ) { // ArrayInitList
Array<T, sz> temp;
va_list ap;
va_start( ap, first );
temp[0] = first;
for( size_t i = 1; i < sz; i++ ) temp[i] = va_arg( ap, T );
va_end( ap );
return temp;
}
template<class T, size_t sz, size_t n> // 一応用意
Array<T, 0> AIL() { Array<T, 0> temp; return temp; }
struct A {
typedef Array<int, 10> myArray;
const myArray array;
A( const myArray & a ) : array( a ) {}
};
int main() {
A obj1( AIL<int, 5>( 10, 20, 30, 40, 50 ) ); // <- こんな感じで引数をグループ化します
for( int i = 0; i < 10; i++ ) cout << obj1.array[i] << endl;
A obj2( AIL<int, 10>( 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ) );
for( int i = 0; i < 10; i++ ) cout << obj2.array[i] << endl;
return 0;
}
147 :
106 :2001/02/18(日) 19:20
>>141 ひょっとして,1回目の読み込みでios_base::eofbit
が立ってませんか?
シーク前にclear()を呼んでみて下さい。
ifstream ifs("filename");
<-- 読みこみ処理 -->
ifs.clear(); // <-ここ
ifs.seekg(0, ios_base::beg); // <- ポインタを先頭に
<-- 読みこみ処理 -->
148 :
141 :2001/02/18(日) 22:04
ifs.clear()を使用することでうまくいきました。 どうもありがとうございます。 処理系はVisualC++6.0 SP4 on NT4.0です。 ios_base を使おうとしたら、シンボルエラーで使えなかったので ios::begのままです。 調べてみると、インクルードファイル(.h)にはios_baseクラスは 見つからなかったのですが、どうしてでしょうか?
149 :
106 :2001/02/18(日) 22:45
>>148 うまくいって良かったですね。
>ios_base を使おうとしたら、シンボルエラーで使えなかったので
ios::begのままです。
調べてみると、インクルードファイル(.h)にはios_baseクラスは
見つからなかったのですが、どうしてでしょうか?
拡張子のつくC++用の標準ヘッダファイルは,規格化以前の古い
仕様です。その古い仕様のライブラリでは,ストリームクラスの
最も基底なクラスはiosでした。
というわけで,VisualC++6.0 SP4 on NT4.0がC++の標準規格に
準拠していて,事情が許すのなら,<iostream.h>ではなく,
<iostream>を使って,標準規格にそったライブラリを使うことを
すすめます。
150 :
保田圭 :2001/02/20(火) 02:43
私の悩みを聞いてください。このようなコード(もちろん簡略化したもの) char input_buffer = new char[1000]; char output_buffer = new char[1000]; strcpy(input__buffer,"ABCDEFG"); strcpy(output__buffer,input_buffer); delete input_buffer; delete output_buffer; を実行し、input_bufferとoutput_bufferをウォッチリストにいれて観察 するとoutput_bufferの中身が消されずリークができてしまいます。どうして でしょうか?わたしは初心者以下だからでしょうか?ハロプロのコンサートに 向けていち早くこのコードを完成させなくてはなりません。教えてくれた方に は私の処女上げます。辞退なさっても結構ですけど。
とりあえず delete [] input_buffer; delete [] output_buffer; としてみよう。
152 :
デフォルトの名無しさん :2001/02/20(火) 04:49
inline 関数を C++ ファイルに extern でなく static リンケージで定義する方法がわからなくて悩んでいます。 よろしければどうか教えて下さい。 --- header class Hage { private: inline void f(); } --- c++ file inline Hage::f() { ... }; --- と定義すると friend のために .global なやつも コンパイルしてしまうのでサイズが膨れて勿体無いです。 こういうのも考えたのですが static inline Hage::f( class * phage, ... ) { phage->.. = ; } もっと綺麗に書けないでしょうか?
153 :
保田圭 :2001/02/20(火) 13:07
>>151 試したわよもう。でも不思議と何も起こらない。よかったら 試していただけないでしょうか?
154 :
IE :2001/02/20(火) 14:21
>>150 >>153 突然ですが、
char input_buffer = new char[1000];
char output_buffer = new char[1000];
を
char *input_buffer = new char[1000];
char *output_buffer = new char[1000];
こうしてみたらどうです?
155 :
IE :2001/02/20(火) 14:22
教えてください。 C++、またはWinAPIで、 IEのバージョン取得をしたいのですが。。。
156 :
デフォルトの名無しさん :2001/02/20(火) 14:24
157 :
106 :2001/02/20(火) 14:53
>>152 うーん,いってる意味がよくわかりません。
「friend のために .global なやつも
コンパイルしてしまうのでサイズが膨れて勿体無いです。」
という部分が不鮮明で。friendが登場するなら,それも示して
いただけますか? あと,「global なやつ」ということですが,
これは,「クラスの外で定義されたメンバ関数」という意味でしょうか?
(「クラスの外で定義されたメンバ関数」はスコープ的にはグローバル
ではないので)
これで上手くいかないなら、俺にはわからん。 ちなみに delete は確保したメモリの中を 0 で埋めてから 開放したり、ポインタを NULL にしない。 char * input_buffer = (char *)new char [1000]; char * output_buffer = (char *)new char [1000]; assert( input_buffer != NULL ); assert( output_buffer != NULL ); strcpy( input_buffer, "ABCDEFG"); strcpy( output_buffer, input_buffer); delete [] input_buffer; delete [] output_buffer; // input_buffer, output_buffer は NULL にはならない。
159 :
152 :2001/02/20(火) 16:11
説明不足でした、すみません。(^^;) 152の f() のようにインライン関数の中身をヘッダファイルでなく C++ ファイルに定義すると、見た目すっきりしますよね。 それに外部から呼び出すことはないので private として このオブジェクトファイルで f() を完結させたいと思っています。 (外部にリンケージしないようにしたいなぁと・・) もし他のオブジェクトファイルから f() を呼び出そうとしても private なので呼び出せません。でも実際にアセンブラリストを 見てみるとインライン展開される一方で、外部からもアクセス できるように .global な関数も生成されていました。 ここからは私の推測なのですが、ヘッダファイルで定義されていない 関数にアクセスしようとすると "Unresolved External" あたりの エラーをだしても良い(私としてはここはこれが好ましいのですが) のですが、コンパイラが friend で他の翻訳単位からこの関数を 使用してくることに備えて、.global で外部から呼び出せる名前の 関数を生成しているのかな・・と思いました。
160 :
↑のつづき :2001/02/20(火) 16:12
ヘッダファイルのクラス宣言で f() を宣言しているのが問題に なのでヘッダファイルから削って C++ ファイル側に static inline で 定義したのが下のほうの関数です。でも、こうするとクラスの変数に 触れないんですよね。(^^;;;) それでクラスのポインタを受け取って アクセスするようにしているのですが、アクセスには private やら 問題山積なような。 こういった問題を上手く書く方法があれば・・どうかご教授して いただきたく質問させていただきました。長くなってごめんなさい。 処理系は gcc 2.95 です。
161 :
デフォルトの名無しさん :2001/02/20(火) 16:13
こうやって、HageImpl::f()別に作ったらだめでしょうか。 Proxyパターンですな。 もしHage::f()使わなければ、HageImplはインスタンスも 作られないので、なにかとお得。 class Hage{ HageImpl* impl; Hage(){impl = null;} virtual ~Hage(){if(impl)delete impl;} inline void f(){getImpl()->f();} HageImpl* getImpl(){ if(!impl)impl = new HageImpl(); return impl; } }
162 :
デフォルトの名無しさん :2001/02/20(火) 16:33
>>160 関数定義をヘッダーファイルに直接書いて、
g++ -O
じゃない?
163 :
106 :2001/02/20(火) 17:16
>>159 補足説明,ありがとうございました。以下,ヘッダとソースファイル
が次のようだとして話を進めます。
--- header "hage.hpp"
class Hage {
public: // <- アクセス制御はコード生成には根本的に影響を与えないのでpublicとしておく
inline void f();
};
---
--- c++ file #1 "hage.cpp"
inline void Hage::f() { ... };
---
--- c++ file #2 "main.c" (Hage::f()は使わない)
#include "hage.hpp"
int main() {
Hage h;
return 0;
}
---
--- c++ file #3 "g.c"
#include "hage.hpp" (Hage::f()を使う)
void g() {
Hage h; h.f();
}
---
>152の f() のようにインライン関数の中身をヘッダファイルでなく
C++ ファイルに定義すると、見た目すっきりしますよね。
こうすると,hage.cppの翻訳単位ではインラインになる可能性がありますが,
g.cではインライン展開されず,通常の関数コードとしてhage.cppの翻訳単位に
追加で生成されます。g.cの翻訳単位からは,通常の関数呼び出し手続きを
つかって,このhage.cppの翻訳単位に追加生成された関数コードを呼び出す
だけです。
もしかして,「.global な関数も生成されていました。」というのは,この
通常の関数コードじゃありませんか。
いろいろ状況を見ると,ヘッダファイルにインライン関数の定義を書けば
解決するように思えるのですが....。
--- header "hage.hpp"
class Hage {
public: // <- アクセス制御はコード生成には根本的に影響を与えないのでpublicとしておく
inline void f(){ /* 定義もここで */ }
};
---
164 :
106=163 :2001/02/20(火) 17:24
う,ちょっと説明がまずかったですね。 >こうすると,hage.cppの翻訳単位ではインラインになる可能性がありますが, g.cではインライン展開されず,通常の関数コードとしてhage.cppの翻訳単位に 追加で生成されます。g.cの翻訳単位からは,通常の関数呼び出し手続きを つかって,このhage.cppの翻訳単位に追加生成された関数コードを呼び出す だけです。 とはつまり,インライン指定した関数は,必ずインライン展開されるとは かぎらず,インライン展開できないときのために,通常の関数コードも 生成しておく。ということです。つまり,上の例ではmain.cにf()の通常の 関数コードも追加される,ということです。インライン展開が必ずしも 可能でない状況の例としては,インライン関数のポインタを得るよな場合 なんかがありますね。
165 :
152=159 :2001/02/21(水) 00:40
皆様ご教授いただきありがとうございます。
ソースリストの見やすさと手間を天秤にかけて考えてみました。
クラスの変数を使う場合は、皆様のおっしゃるとおりヘッダファイルに
定義してしまうほうが一番良さそうですね。
そう書くことにしました。
個人的には表に出したくない関数の定義はその翻訳単位で定義できるほうが
美しいと思うんですが・・(他の人が使わない関数なのに、インライン化
するために他の人も見るヘッダファイルにずらっと書くのは分かりづらい
のではないかと・・)
>>161 関数が必要になったときにインスタンスを生成して呼び出すプロクシ型
なんですね。これならメモリを有効に使ったり、必要以上に多くの
オブジェクトが生成されずにすみそうです。
152は生成コードが大きくなってしまっているのでたぶんこの方法では
生成コード自体は小さくならないかもと思うのですが
(間違ってたらごめんなさい)でも、この方法はとても実践的ですね。
166 :
152 :2001/02/21(水) 00:52
>>162 はい。たぶん それがただしいと思います。
ただインライン関数が数百行になってくるとなんとかしたくて・・。
>>163 =164
解説ありがとうございます。
>もしかして,「.global な関数も生成されていました。」というのは,この
通常の関数コードじゃありませんか。
はい、そうです。うーん、、そういえば inline って「できるなら展開する」
なんですよね。とすると friend のため、っていうのは外れですね。
そういえば for ループがあると展開しないコンパイラもあるとか・・。
高速化するために C++ のファイルからヘッダファイルに移して inline にする
と見づらくなっちゃうので、、良し悪しかもしれないですね。
理解が曖昧なので誤解していた部分が、多々あったみたいです。
ご意見で大変勉強になりました。ありがとうございます。
167 :
保田圭 :2001/02/21(水) 03:18
>>158 さんありがとう
まだそのコード試してないんですが、そのコードの意味を教えていただけないですか?
おそらくCharポインタ1000個のArrayとしているんだと思うんですが
そうすると
strcpy( input_buffer, "ABCDEFG");
の部分で何が起きてるんでしょうか?input_buffer[0]にABCDEFGが入るんですか?
それともinput_buffer「0」にA、input_buffer「1」にB。。。となってくれるん
でしょうか?
168 :
デフォルトの名無しさん :2001/02/21(水) 14:18
データベースを使用するアプリケーションの場合、(に限らないのですが・・・) ある特定のデータベースを指すパス+ファイル名などの情報は、どういう構造で 保持するのが、定石なのでしょうか。 ヘッダファイルに記述し、データベースにアクセスするクラスに、読み込ませ、 他のクラスからは、データベースにアクセスするクラスを呼ぶとか、いうのが いいのでしょうか。 定数の定義する位置がいまひとつ分かりません。理屈的にもすっきりする扱い 方とは、どういったものなのでしょうか
169 :
>168 :2001/02/21(水) 14:53
URL文字列をキーとしたハッシュテーブルで良いんじゃない? だめかい?
170 :
デフォルトの名無しさん :2001/02/21(水) 22:29
>>168 何を言っているのかわからないけど、
クラスを設計するときは、
アクセスだとか処理の単位ではなくて
オブジェクト単位で考えたほうがいいよ。
とりあえずUMLでクラス図を書いてみれ。
考えがまとまるぞ。
171 :
デフォルトの名無しさん :2001/02/21(水) 23:51
>>168 INIファイルの中身みたいな、初期定数をメモリ上にしまっておく場所
っつう意味でいいのかな?
連想配列が一番楽だけど、サポートしてない言語ではmapを使おう
(連想配列と殆ど同じ)。
(キー=値)のセットをvectorみたいなの(ぜんぜん違うけど外見上
はそんなもん)で持ってて、キーで問い合わせると値が帰ってくるって
いうコレクション構造を言語仕様でサポートしてる言語っておおいと思うぞ。
Perlの連想配列、C++のSTLのmap、Javaのjava.util.Mapとか。
(VC++のgetPrivateProfile云々あたりをいちいち呼ぶとかはアホっぽい
ので使わんで欲しい。会社のソースにそう書いてあってゲンナリした…
んなもんデータモデルにキャッシュしろよ。)
そんなのを、OOP言語ならSingletonクラスにしとくとか、
そうでないならしょうがないからグローバルにおいとくとか。
Unix関係でマルチプロセスなら共有メモリっつうのもあるかも。
172 :
デフォルトの名無しさん :2001/02/22(木) 09:39
>>170 オブジェクト単位で設計するところと、処理単位でまとめるところの
バランスが(言葉は適切でないと思いますが、オブジェクト指向設計と、
3層構造のバランスが)、アプリのミソだと思っているのですが
(まぁ、今までそれだけ改修,改造の多いプロジェクトにかかわってきた
のが問題なのかもしれませんが。)、理解できるように、もっと頑張ってみます。
>>171 ありがとうございます。
C++だと、その配列はどういうところに記述して、各ソースから
参照できるようにするのが、定石か・・・あたりも教えて欲しいのですが。
173 :
171 :2001/02/22(木) 10:51
>172 STLのmapの使い方はSTL本とかいっぱいあるから そこで良いよね。 それを置いておくところだけど、 初期データクラスを作る、つうのが一般的でしょ。 mapをクラスのprivate staticのメンバにして、mapへの 問い合わせ関数と、初期化(ファイル読み込んでmapへデータ を登録する)関数はpublic staticにしておく。 class Property{ private: static std::map<string,string>* datamap;//最近C++触ってないのでうろ覚え public: static void init(string filename){} static string get(string key){} } 初期化時 Property::init(なんかファイル名); 使うとき string value = Property::get(キー文字列); mapがプログラム内に1個しかいらんのなら、これでええんちゃう? 2個以上の固定数なら、Singletonパターン拡張してヒープに 固定数インスタンス作るよう変更するほうが良いかな。 (やり方はデザインパターン本読んでください。)
174 :
VC++勉強中 :2001/02/23(金) 09:00
VC++で、MDIアプリを作ろうと思っています。 まだまだ初心者の身ですので、AppWizardを使って MDIの大枠を作った後、子ウィンドウとして、数種類のフォームを 使いたいので、CFormViewを追加しました。 ただ、追加できただけで、この追加したフォームの表示の仕方が さっぱり分かりません。 どうすれば、この追加したフォームと、元のフォームを表示することが できるのでしょうか。 メニューAを選べば1つ目のフォームを、メニューのBが選択されたら B2つめのフォームが・・・としたいのです。
175 :
VC++勉強中 :2001/02/23(金) 16:09
うう・・・みなさん、MDIアプリは作られてないのでしょうか・・・ 助けて下さい・・・
>>175 VBやっとけ。
WinAPI覚える前にMFC使うな。
>>176 あんたもできねーんだろ(藁
俺もできないから、設計で逃げてるよ
>>175 あきらめなよ
178 :
デフォルトの名無しさん :2001/02/24(土) 14:33
delete this みたいに、自分自身をdeleteするのってどうなんでしょうか? なんか気持ち悪い気がするんですが。こういう書き方ってよく使われるんですか?
179 :
デフォルトの名無しさん :2001/02/24(土) 14:45
>>178 モードレスダイアログを消す時とかのMS推奨方式ですね。
でも、やっぱ気持ち悪い、グェ〜。
180 :
デフォルトの名無しさん :2001/02/24(土) 14:46
C++じゃないんだが、スレ立てるほどでもないので、、、 #include "stdio.h" って、 #include <stdio.h> と何か違うの?
181 :
デフォルトの名無しさん :2001/02/24(土) 15:04
>>178 Ore* Ore::2ちゃんに書き込む()
{
発言を書く;
return ( 逝っていい ? this : NULL );
}
として
delete pOre->2ちゃんに書き込む();
とやる手が紹介されていたよ。
>>180 #include でヘルプ検索しろ。
どのディレクトリから stdio.h というファイルを探すか、がちがうのだ。
ソースを検索するパスが違う。 "" だと作業ディレクトリ、<> だとシステムのディレクトリ。 という理解でだいたい問題ないと思うけど 仕様者のフォロー望ム
183 :
デフォルトの名無しさん :2001/02/24(土) 15:15
:@
184 :
( ´_ゝ`) :2001/03/02(金) 01:34
( ´_ゝ`)ageとこう・・・
185 :
>>174 :2001/03/02(金) 02:23
なんてタイムリーな。自分もちょうどそこで躓いてます。 解決策は見つかりましたか? その後どうなったか教えてください。
186 :
デフォルトの名無しさん :2001/03/03(土) 15:55
ANSI C++に完全準拠しているコンパイラってありますか? C++ Builderが良いところいっているらしいけれど。
187 :
174 :2001/03/06(火) 23:43
>>185 残念ながら、その後は日常業務が忙しくて解決してません。
(日常業務でPGを開発することが無いもので・・・)
185さんは解決しましたか?
どなたか、アドバイス下さい。よろしくお願いします。
#pragmaって何に使うんですか?
>>188 規格で定義されていない、処理系固有の機能を
指定するためだぴょん。
コンパイラのマニュアル読め>188
191 :
185 :2001/03/07(水) 00:34
>>174 同じく行き詰まって他の仕事やっちゃってます。
AddDocTemplate()使うと、追加したテンプレートが、
ファイル新規作成時にMFCがデフォルトで出すしょぼいダイアログから
選択できるようになることはなったのですが、
あれを出さずに185さんがおっしゃるようにメニューから
選びたいんですけどね。
どなたかHELP願います。
185さんって俺のことじゃないか。失礼
194 :
デフォルトの名無しさん :2001/03/07(水) 09:46
>>191 C***App::OnNewFileをオーバーライドすれ。
195 :
186 :2001/03/07(水) 11:15
>193 サンクス。Visual C++はnewしたときに例外を投げないとか、なんとか。 つーわけで完全準拠じゃないみたいですね。
196 :
191 :2001/03/07(水) 13:52
追加したテンプレートへのポインタをメンバ関数に出しといて メニューで呼ばれたときのコマンドハンドラで そのポインタ->OpenDocumentFile(NULL); ってやればできました。有り難うございます。
197 :
七市 :2001/03/08(木) 23:47
MDIの事を書かれている人に質問! 新規作成を選んだ時に出てくるダイアログに書かれている名前は どうしたら変更できるのでしょうか? っていうか、あそこに出てくる名前ってなに?
>>197 CDocManager::OnFileNew()見たら
CNewTypeDlgと言う名前でダイアログ出してて、
そいつのシンボルはAFX_IDD_NEWTYPEDLGで、実体は
:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE\l.jpn\AFXRES.RC(173)
に切ってあった。
結局194さんの言う通りオーバーライドするしかないんじゃない?
199 :
七市 :2001/03/09(金) 09:19
POSITION curTemplatePos = GetFirstDocTemplatePosition(); while(curTemplatePos != NULL) { CDocTemplate* curTemplate = GetNextDocTemplate(curTemplatePos); CString str; curTemplate->GetDocString(str, CDocTemplate::docName); if(str == _T("Hello")) { curTemplate->OpenDocumentFile(NULL); return; } } VCのサンプルを見たら、これでテンプレートに登録したウィンドウを 表示できるようです。 curTemplate->GetDocString(str, CDocTemplate::docName); if(str == _T("Hello")) の、CDocTemplate::docNameが、新規作成の時にどのテンプレートを使用するか 選択するダイアログに出てくる名前と等しいような気がします。 とはいっても、このdocNameを変更する方法は判らない。 これがわかれば、何とかなる?
200 :
七市 :2001/03/09(金) 14:30
AddDocTemplate()の一つ目の引数にあるIDR_MDI_xxxxxxという文字列の (\nから始まっているので、1つめは無いとして)2つめがdocName、 3つめが新規作成を選択した時にでてくるダイアログに表示される名前(文字列)だね MSDNのCDocTemplate::GetDocString に書かれてた。 このStringTableに新しく文字列を追加してAddDocTemplate()するときに 使えば、色々なテンプレートに色々な名前を付けれるのでは?
>>197 ,199,200
>新規作成を選んだ時に出てくるダイアログに書かれている名前
というのはダイアログ自体のことじゃなくて、選択するテンプレートのタイトル文字列
のことを言ってるんですね?(ちょっと勘違いしてました)
っていうかもう答え出てるんでしょ。
202 :
七市 :2001/03/10(土) 01:01
>新規作成を選んだ時に出てくるダイアログに書かれている名前 >というのはダイアログ自体のことじゃなくて、選択するテンプレートのタイトル文字列 >のことを言ってるんですね?(ちょっと勘違いしてました) そうです。 これについてはもう答えが出たけど、 よくよく画面をみると、ウィザードで作ったIDR_XXXXXXTYPEを 使ったテンプレートを開くとメニューバーに「ウィンドウ」とかが追加されるのに 自分で追加したIDR_XXXXTYPEを使ったテンプレートを開くと メニューバーが変化しないのです どして!?
203 :
七市 :2001/03/10(土) 11:34
またしても自己レス IDR_XXXXTYPEのストリングだけでなく、メニューも必要なのですね VC++の事なので板違いですね 自粛します
204 :
デフォルトの名無しさん :2001/03/13(火) 05:04
かなり初心者な質問ですがよろしくお願いします。 LAMEのソースファイルをbolandC++Compiler(無料のやつ)でコンパイルしたいのですが どうしていいか全く分かりません。 1から教えて下さい。
205 :
デフォルトの名無しさん :2001/03/13(火) 05:14
C++というかCの質問なのですが、 テキストファイルから文字列読みこむときって scanf("%s", s); みたいにやりますよね。このとき配列sには、リターンか スペースかタブまでの文字列が入ります。そこをなんとかして、 スペースやタブは無視してリターンまで(1行全部)をsに 読みこむ方法ってありますか?
206 :
デフォルトの名無しさん :2001/03/13(火) 06:17
>205 バイナリで開いて自分で分割する '\r''\n' の2文字が改行コード。 通常は2文字続いてるが改行コードの違うマシン(UNIX、MAC) で作られたファイルはどっちか一方のみ。
207 :
205 :2001/03/13(火) 06:24
208 :
>207 :2001/03/13(火) 07:54
fgets()ではだめか?
209 :
デフォルトの名無しさん :2001/03/13(火) 12:27
本を見て学習しているのですが 下のコードはdynamic_castの実験を行うものなのですが #include <iostream> #include <typeinfo> using namespace std; class B { virtual void f() {} }; class D1 : public B { void f() {} }; class D2 : public B { void f() {} }; int main( void ) { B *p; D1 ob_1;//今回は使用しません D2 ob_2; p = dynamic_cast< D2 *> ( &ob_2 ); //ここが問題のようです if( p ) cout << "成功しました。\n"; else cout << "失敗しました。\n"; return 0; } --------------------構成: test_01 - Win32 Release-------------------- コンパイル中... test_01.cpp C:\Windows\デスクトップ\プログラミング\プログラム\test_01.cpp(26) : warning C4541: 'dynamic_cast' が /GR- を使用したポリモーフィック型 'class D2' で使用されています; 動作結果は保証されません。 このような警告が出てきてしまい、実行すると 何らかのメッセージが出てきて止まってしまいます。 何が原因なのでしょう、誰か教えて下さい。
210 :
ミトコンドリ子 :2001/03/13(火) 12:31
MSDNでC4541を調べてごらんなさい。ちゃんと書いてあるから。
211 :
209 :2001/03/13(火) 12:41
>>ミトコンドリ子さん ホントだ書いてありました。 そこに書いてある通りに設定を変えたら 出来るようになりました。 それにしてもC4541って普通解らないですよね どうやって知ったのですか? エラーメッセージには書いていないようだし..
あら、アナタの書き込みに「warning C4541」って書いてあるじゃない。 もっと注意力を養ってちょうだい。
ええさっき気がついたんです。 これは便利です、さっきも有効利用しました。
ミトコンドリ子さんもしかして 貴方はネカマですか?
215 :
デフォルトの名無しさん :2001/03/13(火) 20:51
>>205 string buff;
getline(cin, buff, '\n');
C++なら素直にこうしろや。
cinは適当なストリームに書き換えてくれ。
217 :
デフォルトの名無しさん :2001/03/19(月) 03:53
えーと、質問させてください。 入力ストリームから一定のバイト数(10Kバイト程度)のデータを読み込んで、 それをstringオブジェクトに格納したいのですが、その場合、 char buf[10000]; ifstream file("hoge.dat"); file.read(buf, sizeof(buf)); string str(buf, sizeof(buf)); のように、いったんchar配列に読み込んでからコピーする方法しか わかりません。なんか無駄なことをやってるようで気持ち悪いです。 データをstringに直接readするとか、char buf[]をそのまま使って stringオブジェクトを構築することはできないでしょうか。
219 :
217 :2001/03/19(月) 17:23
うう。。すいません。いまちょっと検索したら stringstreamっていうと数値<=>文字列変換の例しか出てこないんで よろしければもう少しヒントをくだせえ。。。
>>219 =217
あ、わり、stringstreamかんけーないや。
何勘違いしたんだろう・・・鬱だ・・・。
>>220 いえいえどーも。レスありがとうございました。
引用厨房モード(プログラミング言語C++ 第3版 p.685) template<class Ch, class Tr, class A> basic_istream<Ch, Tr>& operator >> (basic_istream<Ch, Tr>&, basic_string<Ch, Tr, A>&); template<class Ch, class Tr, class A> basic_ostream<Ch, Tr>& operator << (basic_istream<Ch, Tr>&, const basic_string<Ch, Tr, A>&); template<class Ch, class Tr, class A> basic_istream<Ch, Tr>& getline (basic_istream<Ch, Tr>&, basic_string<Ch, Tr, A>&, Ch eol); template<class Ch, class Tr, class A> basic_istream<Ch, Tr>& getline (basic_istream<Ch, Tr>&, basic_string<Ch, Tr, A>&); <<演算子は、ostreamに文字列を書き込む。>>演算子は、空白文字を終了子とする単語を文字列に読み込み、単語を保持するために必要なサイズに文字列を拡張する。冒頭の空白は読み飛ばされ、末尾の空白文字は文字列の中にはセットされない。 getline()関数は、eolを終了子とする行を文字列に読み込み、行を保持するために必要なサイズに文字列を拡張する。行終了子はストリームから取り除かれるが、文字列の中にはセットされない。stringは入力にあわせて拡張できるので、ストリームの中に終了子を残しておいたり、文字配列用のget()やgetline()のように読み込む文字数を指定したりする必要はない。
223 :
デフォルトの名無しさん :2001/03/20(火) 10:39
もともとJava使いで、最近C++のSTLに 手を出し始めたのですが、 stlのvector = java.util.Vector stlのmap = java.util.Hashtable このような認識でいいのでしょうか? mapってのが聞きなれないので、 いまは、ラッパークラスで包んで Hashtableって名前にして使ってます。
224 :
通りすがり :2001/03/20(火) 11:06
>>223 mapというのは抽象的なデータコンテナを表す名前なのに対して、Hashtableというのはその実装方法を表す名称です。
mapテンプレートクラスは二分木で実装されているようです。一般的にはハッシュ表の方が二分木より高速に検索できますが、それぞれの型ごとにハッシュ関数を用意する必要があります。mapテンプレートクラスでは <演算子さえ定義されていればどんな型でも使えますし、仮に<演算子がなくてもハッシュ関数より簡単なless関数だけ用意してやれば済みます。
>>224 そうそう。
C++のmapのほうが概念的にスマートだよね。
226 :
デフォルトの名無しさん :2001/03/20(火) 11:55
>225 インタフェースとしてはテンプレートがあるぶん良さげだけれど、 (mapの)実装まで決まってるのはやーねー。 インタフェースと実装が分離されているほうがスマートじゃない?
227 :
デフォルトの名無しさん :2001/03/20(火) 11:56
>223 つーか、MapはJavaにあるぞ。 インタフェースだけれど。
228 :
223 :2001/03/20(火) 12:27
>>224 さん
詳しい説明ありがとうございました。
大体理解できました。
STLのコンテナの概念がわかってないことが
バレバレで恥ずかしいです。
JavaのHashtableが、ハッシュ関数(Objectクラスの
hashCode)をオーバーライトしたものにしか有効で
無いのに比べ。
mapは、どんな型にでも適応できるということですね。
<演算子というのがいままで使ったことが無いのですが、
小なり演算子ですよね…
==演算子で無いのには何か理由が?
operator <()にてこれを再定義しておけば、良いと
>>227 さん
開発をずっと1.1.6ベースでやっていたのでMapって
使ったことが無かったんですよ。
(1.2からサポートでしたよね?)
229 :
223 :2001/03/20(火) 12:32
自己レスですが、 よく考えたら、2分木だから <演算子を定義しなければ ならないってことですかー アホだ…<自分
230 :
デフォルトの名無しさん :2001/03/20(火) 13:14
>>228 そかそか。collection API は Java 2 からだからね。
でも、一応は collection API は単体で配布してる。
231 :
デフォルトの名無しさん :2001/03/24(土) 05:36
C++初めて半年以上になるけどいまだに ostringstream のバッファのクリアの仕方知らない・・・ string::eraseに値するようなメソッドって無いっすか?
みんなストリーム入出力って使ってるんだろうか・・・。
>>231 stringstream strstr;
strstr.str("");
233 :
デフォルトの名無しさん :2001/04/11(水) 10:34
newをオーバーロードして、メモリが確保された場所を デバッグ表示させたいのですがいい方法はないでしょうか? // こんな感じにオーバーロード出来ると嬉しい。が、無理だし。 void *operator new(size_t size, char *file, int line) { printf("%s:%d: %d byte allocate\n", file, line, size) return malloc(size); }
234 :
デフォルトの名無しさん :2001/04/11(水) 10:46
>>228 JavaのMapの実装はHashtable方式だけじゃないぞ。
SortedMapの実装でTreeMap(2分木Map)もコアにあるぞ。
Map継承して自分で実装かくのも良いかもね。B*ツリーMapとか。
235 :
デフォルトの名無しさん :2001/04/11(水) 12:26
ところで、クラス名の頭には「C」ってつけるけど、構造体にはどうしてますか?
クラス名の頭に「C」なんて付けるか?
頭にCついているのはMFCのクラスじゃない? 僕はつけたくないけれど。
>>235 僕は、
class CMusic
とか
typedef TMouse
とかしてます。
239 :
デフォルトの那梨さん :2001/04/11(水) 14:54
>>232 結構未サポートなんだ。それ欲しいんだが。
240 :
デフォルトの名無しさん :2001/04/11(水) 22:19
インラン関数って何?
241 :
デフォルトの名無しさん :2001/04/11(水) 22:24
sexy()
242 :
デフォルトの名無しさん :2001/04/11(水) 22:32
>>235 MFC汚染済みか・・・哀れな。
>>238 >typedef TMouse
パスカル人が見たら、こんらんして仲間を攻撃しだすかもな・・。
つーか、そもそもクラスと構造体でプレフィクス分ける意味あんのか?
243 :
シロート :2001/04/11(水) 22:36
クラス名の頭にC、メンバ変数の頭にm_て 付けなさいって林せんせえが言ってたんですが。 これは違うのですか?
244 :
デフォルトの名無しさん :2001/04/11(水) 22:43
Windowsで普通のウインドウやエディットコントロール等Window系 の物をいじる基底クラスなんか作ってます。 そのクラスの中のメンバ変数でHWNDをもたせて SetWindowTextとかをメンバ関数内で呼び出したりしています。 ようはAPIにかぶせたりしているだけです。 主にこのクラスから派生させて各種コントロール用のクラスとかを 作ろうと思っているのですが・・・ このような(に限った話ではないんですが)基底クラスのメンバ関数って 全部virtualにしちゃまずいんでしょうか? 「virtualにしない理由」があんまり思いつかないんで 全部virtualにしているのですが。 常套手段はどうなんでしょうか? どのようなときに困るか等も一言教えていただけると助かります。
245 :
デフォルトの名無しさん :2001/04/11(水) 22:51
>>244 virtualメソッドの機能理解してればおのずと分かるだろ。
多態されると困るメソッドはvirtualにはせんわな。
あと、なんでもかんでもvirtualにすると、VMTが巨大化して重くなる(藁
なんつったりしてな。別に全部virtualでいいと思うよ。
246 :
デフォルトの名無しさん :2001/04/11(水) 22:56
>>244 Effective C++が詳しいかと。
「継承した非仮想関数を再定義してはならない」
とあります。理由も書いてあるんで読んでみては。
逆にいえば、派生クラスで再定義して欲しくないものは
非仮想関数にする、って感じかな。
あとは実行時の効率の問題。
247 :
デフォルトの名無しさん :2001/04/11(水) 23:09
>VMTが巨大化して重くなる(藁 別にインスタンス毎にVMTが作られるわけじゃないでしょ VMTへのポインタを持つだけだからサイズは関係ないんじゃ?
>>233 なんで無理なの?
そんな感じでいいんじゃ?
C++で構造体が"デフォルトパブリッククラス"になっていると 聞いたのですが、これって意味のあること? クラス使うならクラスでいいじゃん。 おれにはよく分からん。
250 :
デフォルトの名無しさん :2001/04/12(木) 00:18
>>249 だからクラスなんだよ。
で、デフォルトパブリックにすることで、セマンティクス上では
struct と同じになってる。もう構造体は使わないってこと。
251 :
デフォルトの名無しさん :2001/04/12(木) 00:19
最近、難しいのはC++ではなくMicrosoft VisualC++だということがわかってきたんですが、 どうしてMicrosoftはあんな厨房めいたコンパイラを売ってるのですか? そしてなぜそれがこんなに広まってしまっているんですか? 全てが私の理解を超えています。
↑うおお、奇しくもC#相談室とならんどる!!!! これも時代の流れか…。
254 :
デフォルトの名無しさん :2001/04/12(木) 05:37
質問です。 newで確保したクラスは必ずdeleteしなくてはならないのでしょうか? アプリが終了することが前提ならdeleteしなくてもオッケー? それとも、malloc/freeと同じ問題ですか? それだったらスマソ。
deleteしないとデストラクタが呼ばれないけど。 それでも良いならいいんじゃない。 ひょっとしてデストラクタの意味がわからないんだったら、 もう一度本読み直した方がいいと思うけど
ついでに言うと、newしたインスタンス(あんたのいうクラス)は アプリが終了してもdelete呼ばない限りデストラクタ呼ばれないからね。
257 :
233 :2001/04/12(木) 09:21
>>248 あんな感じで出来そうなんですが、
newのプロトタイプが、
void *operator new(size_t size);
なので引数を追加するとオーバーロードされないんですよ
>>257 なんで?233ので引数付きnewを定義しといて、あとは普通に
ClassA* pA = new( __FILE__, __LINE__ ) ClassA;
とかすれば解決な気がするんだけど。
259 :
233 :2001/04/12(木) 13:04
>>258 あんたすげーよ。
その通りにやったらうまくいったよ。大感謝。
newのオーバーロードなんてした事ないよ。俺って厨房 リーク発見とかだよね? BoundCheckerでいいじゃん(泣)
>261 indexを見た瞬間、アダルトサイトだと思ったのは俺だけ?
263 :
デフォルトの名無しさん :2001/04/19(木) 18:00
g++で自己参照型クラスとかメンバにSTLのvectorとかiteratorを含んだクラスのオブジェクトを ダンプ、シリアライズする方法ってどうしたらいいんですか?なんかいいライブラリとかあるのかな? JavaのSerializableインターフェースみたいな感じで使えるとありがたいんだけど。
264 :
デフォルトの名無しさん :2001/04/19(木) 19:36
複数のステートメントがあるマクロを定義する時に #define MACRO do{ 処理1; 処理2; … }while(0); と書いているものを見かけたのですけど、これって中かっこでかこっているのは当然だと思うんですが、doとwhile(0);って何か意味があるんでしょうか。
すみません、よく見たら #define MACRO do{ 処理1; 処理2; … }while(0) だった。そして解決しました。
266 :
グラマっち :2001/04/25(水) 13:13
template <typename T> inline btw<T>::btw( const T &val) : m_val(val) { } template <typename T> inline btw<T>::btw( const T &val) { m_val = val; } では、前者の方が良いらしいのですが、 何がどういいのでしょうか? どなたかご教示ください。
267 :
デフォルトの名無しさん :2001/04/25(水) 13:20
268 :
グラマっち :2001/04/25(水) 14:24
>267 それはわかるのですが、 動作は変わるのですか?
269 :
デフォルトの名無しさん :2001/04/25(水) 14:35
>>266 前者は、
・代入演算子が呼ばれないので効率がよくなる場合がある。
・constメンバを初期化できる。
かな。「Effective C++」に載ってたね。
>>269 では、ディープコピーが必要でない場合は前者の方が良い。
という事ですね、
Effective C++も見てみます!
ありがとうございました。
class CData
{
int a;
public:
CData(int n) : a(n) { printf("set a=%d\n", n); }
CData() : a(0) { printf("set a=0\n"); }
CData &operator=(int n) { a = n; printf("set a=%d\n", n); }
};
class CFoo
{
CData data;
CFoo::CFoo();
};
CFoo::CFoo()
: data(1)
{
}
CFoo::CFoo()
{
data = 2;
}
>>270 こんなテストコードを書いてみたけど、
EffectiveC++ を読んだほうが早いかもしれないな……。
272 :
グラマっち :2001/04/26(木) 18:31
スーパー親切な回答ありがとうございます! 今からやってみます!
274 :
うるう年の考え方おしえて :2001/04/30(月) 23:47
うるう年の考え方おしえて
>>274 スレ違いです。
あとFAQは自分で調べてね。
相談なんですが、 Cと、おジャ魔女どれみって関係あるんですか? おジャ魔女どれみ←C おジャ魔女どれみ#←C# もーとおジャ魔女どれみ←C++ 関係ないよね?
>>276 すごく面白いことを書いたつもりで、
モニターの前で有頂天になっている無様な姿が目に浮かぶようだよ。
278 :
デフォルトの名無しさん :2001/05/03(木) 15:26
vector<int> *v = new vector<int>(1); .. cout << v[0]; でエラーでますよね? cout << v->operator[](0); とするしかないのでしょうか?
cout << v[0][0]; newする(どこかに保存する)必要が無ければ、素直に vector<int> v(1); でいいし。
それとも、望む動作はこっちか? ostream& operator <<(ostream& stream, const vector<int>& v) { for (vector<int>::const_iterator it = v.begin(); it != v.end(); ++it) { stream << *it << endl; } return stream; }
281 :
278 :2001/05/03(木) 16:14
ありがとう。
>>279 のように要素にアクセスしたかったのれす。
new しないで逝ってみようとおもいます。
282 :
デフォルトの名無しさん :2001/05/03(木) 16:42
ん cout << (*v)[0]; じゃだめなの?
283 :
281 :2001/05/03(木) 18:05
>282 ありがとー。演算子の優先順位・・・。 cout << *v[0] とかやってエラーだしてました。
285 :
デフォルトの名無しさん :2001/05/04(金) 07:57
前々から疑問に思ってること、質問させてください Aというクラスと、それをリストで持っている管理クラスBがある。 なんてことはよくありますよね。で、管理クラスBが、Aのメンバを keyに使い、Aのリストをソートするという場面も日常的にあると思います。 現在はA->getKey()みたいなのでkeyを返しているのですが、メンバ一つを返す だけの関数使うのってどうもスマートじゃない気がして、いつも不安にかられて います。こういう管理を実現するスマートな設計って無いものでしょうか。 (もちろんfriendは勘弁で)
>>285 A側にKeyの比較関数を作っといて、
ソートの時はB側でそれを呼ぶとか。
287 :
デフォルトの名無しさん :2001/05/04(金) 13:32
STLだとかのリファレンスってどこかで落とせますか?
C++って、なんで実行時型情報からインスタンスを生成できないのでしょうか? MFCのCRuntimeClassを使えばできるけど。あれはマクロでめんどくさい。 実装してない理由でもあるのでしょうか?
>>288 リンク時に、必要なライブラリの選択が出来ずに、
実行ファイルが巨大化するからだろ。
290 :
>>285 :2001/05/04(金) 18:30
AのStatic メンバにBを持たせるのは駄目か?
>>289 なるほど。
でも、よく考えたら実行時に保持すべき情報が多くなるからかな?
例えば、クラスのサイズとか、コンストラクタへのポインタとか。
全てのクラスについて保持すると莫大になる。
292 :
デフォルトの名無しさん :2001/05/04(金) 22:00
4: virtual string aMethod() = 0; と宣言すると Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland a.cpp: エラー E2462 a.cpp 4: 'virtual' はテンプレート以外のメンバー関数だけに適用できる エラー E2303 a.cpp 4: 型名が必要 エラー E2139 a.cpp 4: 宣言に ; がない と出ます。g++だったらコンパイルとおるんですけれど、 どっちが正しいの?
293 :
デフォルトの名無しさん :2001/05/04(金) 22:12
stringをstd::stringに直す
294 :
292 :2001/05/04(金) 22:15
>293 ありがとう。あたまに using namespace std と加えておきました。
295 :
285 :2001/05/05(土) 01:31
レスありがとうございます
>>286 おおなるほど、それなら無様にメンバさらすの避けられますね。
実際作るとなると・・・バブルソートで実装する位しか思いつかない自分が
憎いです(^ ^;んーこれをSTLこみで作れたら最高ですねぇ。
>>290 Aが関連するのが、Bのクラス(あるいは唯一のインスタンス)なのか、それとも
Bのインスタンスなのかによりますよね、たぶん。前者なら有効そうですが…、
やはり往々にして後者の場合が多いですからねぇ。というか私の状況説明不足です。スマソ
296 :
デフォルトの名無しさん :2001/05/05(土) 01:47
OOPって何ですか?
OOPで検索してね。
298 :
デフォルトの名無しさん :2001/05/05(土) 02:12
ちょっと質問があります。 参照カウンタ付のオブジェクトを扱うスマートポインタを実装したんですが、 このスマートポインタに対して&演算子を使うと格納しているオブジェクトの ダブルポインターを返すようにした所、listなどのSTLコンテナに格納出来なく なってしまいました。 こんな感じのエラーが出ます。 error C2664: 'destroy' : 1 番目の引数を 'class foo ** ' から 'class ref_ptr<class foo> *' に変換できません。 同じ事を_com_ptr_tもやっているのですが、_com_ptr_tはこの問題が生じません。 _com_ptr_tの定義を眺めてみたんですが、どうして_com_ptr_tはOKで私のが駄目なのかわかりません。 よろしくご教授お願いします。
>>298 スマートポインタの & 演算子を、rep へのポインタの取得に書きかえちゃったんだから、
「スマートポインタへの参照」ができなくなっちゃったということでは?
300 :
298 :2001/05/05(土) 03:17
>>299 うい、そういうことなんです。
でも_com_ptr_t(COMスマートポインタのテンプレートクラス)でも同じ
事してるのにエラーにはならないんですよ。
一体どうして?
301 :
298 :2001/05/05(土) 03:24
いまは結局ダブルポインターを返すメンバ関数で対処してるんですけど、 スマートポインタといえど、普通のポインタとほぼおんなじ感じで使え たほうが良いじゃないですか。 引数としてダブルポインターを要求して、そのポインタに製作したイン スタンスをセットして返す関数とかに、 foo(&rptr); // rptrはスマートポインタ てな感じに書けるようにしたいなぁ、って事だったんですけど。
CAdapt
303 :
デフォルトの名無しさん :2001/05/05(土) 04:46
Borland C++ Builderの初心者向けのヤツ、 定価20000だそーですが、 実際小売店ではどのくらいの値段でしょうか? とりあえず買おうかと。メモ帳とお別れしたいの(笑)
BCBのエディタには期待しない方がいいぞ。>303 VisualC++6のエディタの方がマシ。
>304 そうなんですか。 まあエディタはどうでも良いと言えばいいんですが(笑) ゲームプログラミングをしてみたいのですが、 専門書(と言うより入門書)やら解説サイトの内容を見ると すべてアプリを使用しているので。 Visual C++の方が向いてるならそっちにしてみます。 しかしいくらくらいですかね?学割きくのかな?
306 :
デフォルトの名無しさん :2001/05/05(土) 05:22
>>305 DirectX は VC++ に基本対応なので
ゲーム作るならそっちのほうがいいかもね
google.com で Visual C++ アカデミックパックで
ひいてみそ
オープン価格みたいですね。 店頭にいかなきゃわからないか・・・。 約20000で販売してるサイトがありましたが。 秋葉原はそれより安いかなー。
>306 おお、どーもです。調べてみます。
309 :
デフォルトの名無しさん :2001/05/05(土) 05:35
>>305 3年前に学割で買ったVC++6.0Professionalが12000円だったかな。
今はもっと安いかも。MS製品、学生なら恐れることないよ。
逆に社会人には(T-T)
ageちゃった ちなみにヤマダ電気(^ ^; 秋葉原出ればもっと安いかもね
311 :
デフォルトの名無しさん :2001/05/05(土) 05:58
>>302 >CAdapt
??? 301へのレス?
とりあえずMFCにはそんなクラス無いみたいだけど……
312 :
デフォルトの名無しさん :2001/05/05(土) 14:48
文字列は char* と std::string のどっちを使うべきですか?
313 :
デフォルトの名無しさん :2001/05/05(土) 19:36
両方
314 :
312 :2001/05/05(土) 20:04
使い分け方はどうしたら良いのでしょうか? (C++になってstd::stringだけで統一されたのかと思ったのですが、 const char* という記述を良く見ます。)
315 :
デフォルトの名無しさん :2001/05/05(土) 20:54
string に統一なんて全然されてないよ。 使い分けの方針は「できるだけ string を使う」。
316 :
314 :2001/05/05(土) 21:17
「統一」というのは単に自分が電波を受信していただけです・・・。 "できるだけ string" となると char* と混在して混乱しませんかねぇ。 どっちをつかっても移植性に問題がでることはありませんか?
317 :
デフォルトの名無しさん :2001/05/05(土) 21:32
string(const char *) があるから混在してもあまり 意識しないで書けるよ。というかどの辺で混乱するのか よくわからないなあ。
318 :
314 :2001/05/05(土) 21:42
片方で統一できるのなら統一してしまった方が良いと思いまして。 使い分けがいまいちわからないのでもう少し質問させていただきます。 GoF の「デザインパターン」を読んでいてあるクラスが文字列を const char* _name; で保持しているのを見つけたのですが、 これが string じゃないのはなんででしょう? string の方が記憶域を多く使うことくらいしか原因が思いつかないのですが・・・
319 :
デフォルトの名無しさん :2001/05/05(土) 22:22
読者にstringの知識を強いてまで使うメリットはなかったんでしょう。 例えばstringを使えばコード量が1/10になるんだったら使ったと思います。
320 :
314 :2001/05/05(土) 22:36
>319 ありがとうです。できるだけ string を使うということで解決しました。
321 :
こん :2001/05/07(月) 01:50
ちわ〜 みなさんにはくだらない事なのかもしれませんが、ファイルにpassがかかっていて passがわかったんですけど、passが全角ひらがなでpassを入力するとこは英字しか 入りません。どうやってpassを入れるんですか? 教えてください。お願いします。
322 :
ギコ :2001/05/07(月) 04:39
>>321 メモ帳などに全角ひらがなでpassを書いた後、それをコピー
passを入れるところでctrl+v
ゴホン、あー、あー、んじゃいくかね
二度とここにくるんじゃねぇ、スレ違いの上に板違いじゃボケ
ちくしょうめ、オレがpassの代わりに呪いかけてやる
( ゚Д゚)ノノ〜x〜x〜x〜x〜x<イッテヨシ>
323 :
デフォルトの名無しさん :2001/05/07(月) 18:26
VC++6使ってるのですけど、これが通ってしまうのってどうも納得いきません class Foo{ }; class FooFoo : public Foo{ public: int no(){ return 10; } }; main(){ Foo* foo = new Foo; int result = ((FooFoo*)foo)->no(); //resurt = 10 delete foo; } newしたのがFooFooクラスならまだ納得いくのですが… インスタンスも無いような派生クラスの関数なんぞ 呼び出しちゃえていいのでしょうか?
324 :
デフォルトの名無しさん :2001/05/07(月) 19:01
>int result = ((FooFoo*)foo)->no(); ここを int result = ((FooFoo*)NULL)->no(); にしたって動くんだからさ。(実験してない)
325 :
デフォルトの名無しさん :2001/05/07(月) 19:27
別ファイルを読み込んで、デフォルトの引数として、5を表示 させたいのですが、メインファンクションで、引数なしで呼び 出すと、Carという名前のクラスを実行してくれません。 呼び出しで、Car tk(78);の様に、引数を入れるとちゃんと 実行されます。なにが間違ってるのか、わかる方いれば教えて ください。 //ファイル1 #include<iostream.h> class Car { int a; public: Car(int num = 5){cout << num;} } //ファイル2 #include"toyota.cpp" void main() { Car ty(); Car tk(78); }
Car ty(); だと引数無しのデフォルトコンストラクタが呼び出されそうな気がするので、 Car ty; でどーでしょうか。
327 :
デフォルトの名無しさん :2001/05/07(月) 20:03
Car ty(); と書いたら、ty という関数の宣言になっちゃうからね。
>int result = ((FooFoo*)foo)->no(); >インスタンスも無いような派生クラスの関数なんぞ >呼び出しちゃえていいのでしょうか? よくない。C++でCのキャストを使うのは厨房。 FooFoo *p = dynamic_cast<FooFoo *>(foo); if (p) result = p->no(); が正しい。 int result = static_cast<FooFoo *>(foo)->no(); ならコンパイルは通らない。 int result = dynamic_cast<FooFoo *>(foo)->no(); なら、NULLになるから間違いなく例外割り込みが発生するだろう。 Cのコードを混ぜて、C++の問題だと思うなよ。
>>326 それはおかしいだろ。
Car::Car() と Car::Car(int num = 5) は共存できず、
コンパイルエラーになるから。
共存するコンパイラは ANSI に準拠していないはず。
330 :
325 :2001/05/07(月) 20:58
> FooFoo *p = dynamic_cast<FooFoo *>(foo); このクラス定義で dynamic_cast は使えないぞ、普通は > int result = static_cast<FooFoo *>(foo)->no(); > ならコンパイルは通らない。 通るだろ普通
332 :
321 :2001/05/08(火) 02:41
>322のギコさん どうもすみませんでした。。。こうゆう質問どこでするかわかんないので。。。 教えてくれてありがとうございます。。。
333 :
323 :2001/05/08(火) 03:01
>>328 や、確かにCの問題かもしれませんね。ただ継承がらみでもありますし、さすがに
酷いなと思いまして。そもそもno()はstaticですらないのに…。これが私の
理解不足によるもので、本来なら説明可能なものなのかどうかを問いたかったのです。
>>331 static_castですら通りますねー。こうなるとエラーくるまで防ぐ手だてはない
のでしょうか…。こんなコード書かなければいいのですが…腑に落ちない。
>>324 というか
>int result = ((FooFoo*)NULL)->no();
ばっちり動きましたヽ(´д`)ノなんだか悩んでたのがバカみたい、
おかげで吹っ切れました。「まぁ、いいや」で逝くことにします。
334 :
デフォルトの名無しさん :2001/05/08(火) 03:34
異なるクラスのオブジェクトををSTLのvectorで関連付けて運びたいのですが 仮想関数のオーバーライドがうまくいかないみたいなんです。 VC6.0++ですが、以下のようにしてvectorに格納した各オブジェクトに おまえは誰だ?と聞いてもみんなBaseだよとしか答えてくれません。 各自が自分の名前を言って欲しいんですが・・・。 配列ならばうまくいったんですが、vector でうまくやる方法はないでしょうか? class Base{ public: virtual void who(){ cout << "Base"; } }; class A : public Base{ public: void who(){ cout << "A"; } }; class B : public Base{ public: void who(){ cout << "B"; } }; class cV{ std::vector< Base > data; public: cV(){ data.push_back( A() ); data.push_back( B() ); } void show_who(){ cout << "cV"; for( std::vector<Base>::iterator i=data.begin() ; i!=data.end() ; i++){ i->who(); } } }; main(){ cV v0; v0.show_who(); };
335 :
デフォルトの名無しさん :2001/05/08(火) 05:14
>>334 Base型ポインタの配列ではなく、Base型の配列に派生クラスのインスタンスを
つっこんじゃってるからですよ。やってることは要するに
Base base;
A a;
base = a;
base.cV();
なわけです。cV使ってるのはどうみてもBaseだから、当然BaseのcVが呼ばれます。
でも本当にやりたいのはこれですよね。
Base* base = &a;
base->cV();
ま、もう必要ないだろうけど一応
class cV{
std::vector< Base* > data;
public:
cV(){
data.push_back( new A() );
data.push_back( new B() );
}
void show_who(){
cout << "cV ";
for( std::vector<Base*>::iterator i=data.begin() ; i!=data.end() ; i++){
(*i)->who();
}
}
~cV(){ /*vecotor型dataにあるのを全てdelete*/ }
};
基本クラスポインタの配列やリストを使って派生クラスをdeleteする場合は
基本クラスのデストラクタをvirtualにすることをお忘れなく
> vecotor型data (^-^;
337 :
デフォルトの名無しさん :2001/05/08(火) 11:52
334です。できました。激多謝!>335
338 :
デフォルトの名無しさん :2001/05/09(水) 01:14
再起法をつかって2のk乗を求めるプログラムなんですが、 エラーは出ないけども、数値を入れると強制終了になってしまいます。 何が原因でしょうか?どなたか教えてください。 よろしくお願いします。 #include <stdio.h> int fact(int n) { if (n != 0) return(2^n+fact(n-1)); else return(2); } int main(void) { int x; scanf("%d",x); printf("%d",fact(x)); return(0);}
>>338 scanf("%d",&x); //&が抜けてる
341 :
デフォルトの名無しさん :2001/05/09(水) 01:48
>>339 あ・・・どうもです・・・
なさけない・・・
やさしい。イイ
いまさらだがVisual C++のStandardEditionの アカデミーパックは、秋葉原のソフマップで 税抜き8980円だったことを報告したいと思います。 っつーか買いました。
C++ではないですが DWORD dw; dw = 0xFFFFFFFF; printf("%d", dw); とすると-1が出てきます 0xFFFFFFFEとすると-2が出てきます どうして?unsignedじゃないの??%ldでもだめ よろしくお願いします
346 :
デフォルトの名無しさん :2001/05/10(木) 06:49
>>345 %dはdwのビットイメージをsignedで解釈するから。
%uを試してみれ。
>>344 なんだか自分を責めたい気分。あと一言いっておけば…、と。
>>344 学割なら+3000円くらいで、Pro版買えたのにね
349 :
デフォルトの名無しさん :2001/05/10(木) 19:23
344じゃないけど Proだとなんかちがうんですか?
>>349 MFCのスタティックリンクができたりとか。
最適化もStandardだとダメだったっけ。(あんまり覚えてない)
>347 いやーどーなんですかねー? 別にプロを目指してるわけでもないので スタンダードで良いだろう程度に考えてましたが。 まず不便を感じられるようになりたいですね。
353 :
デフォルトの名無しさん :2001/05/11(金) 20:53
発展してるのでage
>>352 うん、杞憂だったよ。どうせなら…って程度だし、きみなら大丈夫だと思う
勉強なら別に問題ないし、そろそろ次もあるしね
355 :
デフォルトの名無しさん :2001/05/12(土) 10:37
Windows環境でCSVファイルを読まないといけないくなりました。 一行をcharの配列にいれて、一文字ずつカンマを調べようかと思ってますが 何か効率的なやり方や、csvを読むクラスがあれば教えてください〜。
356 :
基本的でごめんね :2001/05/12(土) 13:50
ポインタの参照渡しってどうやるのでしょうか? int a, b, *ptr; ptr = &a; printf("ptr = %X, &a = %X, &b = %X\n", ptr, &a, &b); func(&ptr, &b); printf("ptr = %X, &a = %X, &b = %X\n", ptr, &a, &b); ------------------ // この関数のダブルポインタ引数をポインタの参照渡しにしたい。。 void func(int **pptr, int *pb) { *pptr = pb; } よろしくおねがいしまちゅ。。。
357 :
お騒がせしました :2001/05/12(土) 13:55
int a, b, *ptr; ptr = &a; printf("ptr = %X, &a = %X, &b = %X\n", ptr, &a, &b); func(ptr, b); printf("ptr = %X, &a = %X, &b = %X\n", ptr, &a, &b); ------------------ void func2(int * &ptr, int &b) { ptr = &b; } で出来ましたです。。
>>355 それでだいたい問題ありません。
あとはファイルを読み込む際のバッファリングなどに気を配りましょう。
359 :
ルーマニア人 :2001/05/12(土) 18:33
C++の例外の必要性がわかりません。 戻り値で値を返せば例外なんて必要ないんじゃないでしょうか? どうしてわざわざ、Throwなんて機能があるんですか?
ヽ( ´ー`)ノ オブジェクト思考と例外は相容れない関係なんだよ。>359
ヽ( ´ー`)ノ
>>360 思考→指向。どっちでもいいけどね。
362 :
デフォルトの名無しさん :2001/05/12(土) 18:51
ヽ( ´ー`)ノ ちゃんと読め。>362
>>359 例外クラスを継承してポリモーフィズムできるから、
例外処理はおいしいんだよ。
EFileErrorクラスを継承して、EFileReadErrorやEFileOpenErrorとかを作るんだ。
例外に価値を感じないということは、例外クラスを継承するという考えが欠落しているか、
ポリモーフィズムを理解できていないか、どっちかだろうね。
>>360 -363
なんだか会話が成り立っていません。
>>359 Throwしたものが、メソッドコールスタックのどこででも拾えるんだぞ?
オブジェクト指向うんぬんを除外しても、超便利だぞ?
366 :
デフォルトの名無しさん :2001/05/13(日) 00:08
STLのfor_eachとかのアルゴリズムに渡す関数オブジェクトって値渡しで 定義されてますよね(egcs,VC6)? 関数オブジェクトの中で渡された引数の集計を行って、あとから結果を引出したいことが よくあって、参照渡しに修正したアルゴリズムを作って使ってますが、 なんか漠然と気持ち悪いと思ってます。 …こういった使い方ってどうなんですかね?(質問まで漠然としててスマソ)
コンストラクタの中での致命的なエラーとかはどうするよ? 例外で通知するしかないだろ。
368 :
ルーマニア人 :2001/05/13(日) 20:10
オブジェクト指向との関連はわかりませんが、 例外の必要性(便利性?)はわかりました!みなさん、頭イイですね!! 私も例外の理解が浅かったのがいけませんでした。 クラスでの例外を考えると夢が広がりますね。 あとコンストラクタでのエラー通達方法も初めて気づきました。 皆さんのおかげで、とても幸せになれそうです。
369 :
デフォルトの名無しさん :2001/05/13(日) 20:24
>>366 参照(やポインタ)のほうが値渡しより
役立つことが少し多いと思う。大抵どんな場合でも。
その話もまた一例なんじゃないかと推察します。
>例外
なんてゆーか、プログラム実行の流れと
エラー通知の流れとを、別々に作ってくれた
ってのは凄く嬉しいと思うってのが1つ。
あと例外「クラス」ってのも美味しいよね。
例外の種類分けを、エラー番号なんていうダサダサのやり方より
数段マシな方法で管理できるのは、随分よい。
371 :
デフォルトの名無しさん :2001/05/15(火) 09:46
gea
>あと例外「クラス」ってのも美味しいよね 別に例外でクラスオブジェクトを投げる必要はないし、returnで クラスオブジェクトを返さない理由もないんだけど。
>>372 必要性、おおありだよ。
例外クラスの継承図しだいで、
リカバリーのしやすさが飛躍的に高まる。
375 :
デフォルトの名無しさん :2001/05/16(水) 03:20
int& MyMethod(int n){ return n; } こういう戻り値がint&とかの関数の意味がわかんない。 これってどういうことなの? 関数が参照??? 誰か教えてください。
376 :
デフォルトの名無しさん :2001/05/16(水) 05:55
上の場合はローカル変数の参照を返す事になるので激意味無い というかやったらヤバイが、 int& MyMethod(){static int n=0;return n;} とかだと MyMethod()=3; みたいにしてnに代入できると思う。
377 :
デフォルトの名無しさん :2001/05/16(水) 10:00
参照返しは、メンバ変数を返したり、演算子をオーバーロード するときによく使います。これを使ってるソースは標準C++ ライブラリやMFCの文字列あたりを参考にするといいでしょう。
・例外機構と ・エラーの返り値を数値じゃなくてクラスにすること は全く関係がないと主張してるんだけど。 元レスのエラーコードよりクラスまんせー、っていうのは例外がなくっても 成り立つでしょ?
>>378 例外ってのは、適当な例外ハンドラが見つかるまでスタックを辿る機能があるだろ。
そこにポリモーフィズムを組み合わせて、あるときは基底クラスで、
またあるときは派生クラスでキャッチするのがおいしいんだ。
エラーの種類毎に細かくリカバリしたいときは、できるだけ派生クラスを、
エラーが発生した場所と近いところでキャッチする。
あまりエラーの種類を厳密に判別する必要が無く、たとえば
エラーメッセージを表示して終わりとかいうばあいは、
基底クラスをmainに近いスタックでキャッチするようにすれば、
ファイルの読み込み処理毎にリカバリ処理を書く必要が無くなる。
こうしたことはエラークラスがうまく継承されてないと実現できないし、
またスタックを辿る機能がなければ、基底クラスのキャッチを
呼び出し元に任せることもできない。
だからポリモーフィズムと例外は切っても切れないんだよ。
380 :
デフォルトの名無しさん :2001/05/16(水) 18:23
>>376 -377
つまり、最初から関数の「外」に有った変数を返せ、
ってことだよね?この理解で合ってるっすか?
メンバ変数も、関数そのものの中のものじゃない、っと。
381 :
VB厨房 :2001/05/16(水) 18:24
>>379 とても興味のある回答です、
単純なものでいいので具体的なコードお願いできない?
382 :
デフォルトの名無しさん :2001/05/16(水) 19:10
>>378 >・例外機構と
>・エラーの返り値を数値じゃなくてクラスにすること
>は全く関係がないと主張してるんだけど。
>元レスのエラーコードよりクラスまんせー、っていうのは例外がなくっても
>成り立つでしょ?
うーん。面白い主張だが、なんかノリがちょい違うなあ。
切っても切り離せないってのは確かに嘘だが、
合体させないより合体させるほうが「ごりやく」が
大きいのも確かなんで、まぁ。
例外クラスのInstanceをわざわざ自分で作って自分で返し値として返す
ってのは、可能であってもあんまりメリットないなあ。
ふつーしないじゃん。ソース汚くなるだけ。
成り立つけど成り立たせても意味が無いという。
てゆーか言語お仕着せの例外クラスが無い世界の人は
こういう考え方もするんだなってのが新鮮だった。
すまん。俺の常用言語には例外クラスが有るんで(^^;、
そんな面倒なこと考えたことも無かったよ。
383 :
375 :2001/05/16(水) 19:43
>>377 メンバ変数にアクセスするのは普通にメンバアクセス関数を
作ればいいですよね。
ということは、参照返し関数は演算子のオーバーロードくらいにしか
使うことはないんだね。
どうもありがと!
>>381 探してみたけど、ぴったりこれだというページは見つからなかった。
簡単に書くなら、こんな感じか。
foo()
{
char *p1 = new char[256];
char *p2 = new char[256];
char *p3 = new char[256];
char *p4 = new char[256];
foo();
foo();
}
bar()
{
try
{
foo();
} catch(bad_alloc &e)
{
cout<<"メモリがねぇぞゴルァ!"<<endl;
} catch(exception &e)
{
cout<<e.why()<<"だってさ"<<endl;
}
}
あとはstlのexceptionの継承図でも眺めてね。
Javaでも可。
例外クラスを継承構造にするのは、エラー処理の責任の問題。
誰が何のエラーに責任を持つのかはっきりさせることができる。
言い換えれば、責任がもてないエラーはキャッチしなくてもいい。
もしくはキャッチした後で、責任がもてないと判明したら、
より強い責任を持つはずの呼び出し元にthrowする。
こうすることで、各関数が持つ責任を減らすことが出来る。
サンプルコードの例では、fooはメモリ確保エラーの責任を負っていないし、
負ったところで何もできないはず。
エラーコードを使う方法は、呼び出した関数が返したエラーに
必ず責任をもたないといけなくなる。
サンプルコードの例では、fooはメモリ確保1つ1つを、
正しいかどうか管理する、無駄な責任を負う。
呼び出し先のエラーコードを呼び出し元へ伝達することも
一つの責任だ。
そしてmain関数は、他の関数が責任を取れなかった
全ての例外に対する責任を負わないといけない。
エラークラスは必ずstd::exceptionを継承しているなら、
これをキャッチしてエラー内容を表示することができる。
だからintやstringを安易に投げてはいけない。
...では、main関数でキャッチしても、十分な責任を負えない。
>>384 しまった、再帰が永久ループになってる。
単にメモリを確保する関数をさらに呼び出している、
と書きたかっただけなので、
以下のように読み替えてください。
foo()
{
char *p1 = new char[256];
char *p2 = new char[256];
char *p3 = new char[256];
char *p4 = new char[256];
foo2();
foo2();
}
foo2()
{
char *4 = new char[256];
}
>>385 もうちょっとおちつくアルよろし。
>char *4 = new char[256];
char *p4 = new char[256];
387 :
デフォルトの名無しさん :2001/05/17(木) 13:18
ちょいごめん。 Perlの連想配列って、C++だと何になるの?
mapかもな
389 :
デフォルトの名無しさん :2001/05/17(木) 15:33
ハッシュのこと?
391 :
デフォルトの名無しさん :2001/05/18(金) 00:29
初期化にどうしても引数が必要なオブジェクトを Singletonパターンでスマートに実装する方法ってありますか? 初期化メソッドを用意するしかないんですかね、ヤパーリ
>>389 ハッシュテーブルをmapの実装手段にすることはあるけど…
連想配列の実装を、2本のvectorにしようと、2本の配列にしようと、
場合によってはBツリー使おうと、それは実装者の自由でしょ。
ハッシュ=mapつうのは、なんか勘違いしてるぞ。
>392 一応フォローしとくとさ、389は単にPerlの連想配列ってハッシュのこと? て聞いてんじゃねーの?最近(?)名前が変わった(連想配列→ハッシュ)らしーから。
394 :
389 :2001/05/18(金) 09:35
すんません。 言葉足らずでした。 393さんの言うとおりです。
395 :
デフォルトの名無しさん :2001/05/18(金) 15:56
>>392 ハッシュ値が得られないからmapの実装にハッシュは使えないと思う。
396 :
VC++です :2001/05/18(金) 22:38
コンパイル時に配列の大きさがわからないという場面に出くわしたので、STLのvectorクラスを使うことにしました。 STLのvectorクラスは自分で作った構造体などは使えないんですか? vector <oreno_kouzoutai> hoge; などとやったらエラーが70出てきて、しょぼんとなりましたよ。
エラーの内容をMSDNで調べろ。話はそれからだ。 3時間調べてわからなかったら、エラーの内容を正確に書いて再投稿せよ 話はそれからだ。 適切な回答が得られるかは、君の質問文作成スキルによるがな...
398 :
デフォルトの名無しさん :2001/05/18(金) 22:59
C++の例外処理について質問があります。 どうもいまいち例外の使い方(上手な使い方)がわからないので困っています。 まずthrowする物について。 C++の本を見るとたいてい例外でエラー用のクラスをthrowしています。 そしてこれらの例外クラスはエラー別に分かれていると思います。 例外用のクラスを使って安全に開放するというのはわかります。 しかし、この例外クラスは何処に記述したらよいのだろうか? と悩んでいます。 今は仮にAというクラスがあった場合Aクラス用の例外クラスを Aクラスを記述してあるヘッダに記述しています。 しかし、エラーの種類別にクラスを作っているとそれだけ 名前空間を占有する事になります。(何かいまいち) 仮にnamespaceを使ったとしても、例外を受け取るのは Aクラスの外の場合も多いと思うので、結局そのAクラスのヘッダを インクルード & using...する事になると思います。 するとエラー用のクラスが多くなってごちゃごちゃしてしまいます。 さらにその他のクラスと同じような例外を通知するのに 同じような例外クラスを何個も作るのはいまいちなきがします。 それならばと各クラス共通の汎用的な例外クラスMemoryError等を作成したとします。 (例外専用ヘッダ&ソース作成。開放等はデストラクタ任せで主にエラーの通知に使う) すると自作のクラスライブラリすべてでその例外クラスヘッダをインクルードする事になります。 それだと、各クラスのソース的なまとまりというかなんというか(説明下手でスイマセン) そういうものが薄れてしまってやっぱりいまいちなきがします。 ながくなったので続きます。スイマセン
399 :
デフォルトの名無しさん :2001/05/18(金) 23:10
つづきです。 自作例外クラスヘッダ等を複数のクラスからインクルードするのは抵抗があります。 それならば標準でついている例外クラスを派生させずにそのまま使うとします。 (標準ヘッダならある程度なっとくできるので) しかしそれでは本当に文字列ぐらいしか通知できません。 わざわざクラスにする意味が薄れてしまいます。 例外にクラスを使うのは主にリソースの開放等安全に終了させるための物 だと思っています(まだよくわかってないですが) そこでまた疑問が湧いてきます。 ある処理の途中で例外が発生した場合その例外以前で確保したメモリを 開放したり、安全な処理をさせなくてはなりません。 そしてそれらの事は例外クラスを使わなくてもデストラクタによって 適切に行われるのが理想だと思います。 するとやはり例外をクラスで投げる必要があるのだろうかと考えてしまいます。 そこでまた悩みが増えます。 オブジェクトが自分自身のデストラクタで安全に終了させるのが理想だと書きました。 そのためにはちょっとしたバッファをnewで確保する時にもSTLのauto_ptr等を 使用したり、ほぼすべての物をクラスで管理するべきなのだろうと悩みました。 まだつづきます(長文スイマセン)
>>398 -399
3行で要約しろ。話はそれからだ。
401 :
デフォルトの名無しさん :2001/05/18(金) 23:20
続きです。 ここから書く事は若干別問題という気がしますが一応聞いてください。 結局のところC++はクラスとSTLを中心に作っていくのが正しいのだろうと 感じました。 ・・・・しかし この辺ちょっとあやふやなんですがSTLって一応C++的に標準なんですよね? ところがSTLをサポートしていない環境というものがあります。 そこでauto_ptr的なものを自作するとします。 しかしそこでまた 「自作の汎用クラスをその他のクラスでインクルードするのはソース的なまとまりが無くなるような気がする」 という悩みが出てきます。 なんかC言語で作っている時とあまり変わらないような気がしてくるのです。 例外とはいかに使うのが正しいのかどなたかアドバイスをください。 お願いします。 ・・・・・・STLを使えない具体例とはWindowsCEなのです。 そこでまた例外とSTLについて悩みが出てきました。 まだつづくんですがちょっとこれまでの質問とは別分野になるのでいったん切ります。
402 :
聞こえてるか? :2001/05/18(金) 23:22
403 :
398 399 401 :2001/05/18(金) 23:26
>>400 長すぎですよね。(ごめんなさい)
1:例外の正しい使い方とは?
2:デストラクタで安全開放するのなら例外でクラスを投げる事にどのような有効利用があるだろうか?
3:例外用のクラスを多数追加する事に抵抗があるのですが普通なのでしょうか?
>>397 Roger. ・・・って俺(396)に向かって言ったんですよね?どちらにせよ、少し調べるのをさぼってました。
スイマセン。
405 :
398 399 401 :2001/05/18(金) 23:28
>>402 400を見る前に401を書いていました。
(書いてる間に更新していなかったので時間差が・・・)
ごめんなさい。
age
age
age
age
age
411 :
デフォルトの名無しさん :2001/05/19(土) 00:30
恐らくkylix相談室を荒らしたのと同一犯。
解決しました。vectorはテンプレート引数を比較するコードがあるのを発見しました。(というか、コンパイラが 教えてくれたエラー内容そのものです。何やら長いエラーメッセージだったので、読み飛ばしていました・・・) するってえとvectorは、構造体は駄目なんですね。仕方なく構造体へのポインターにすることにより回避しました。 って言うか、これは完璧な一人相撲ですね。こういう幕引きは辛いものがあります・・・。
>>413 struct Foo{ int m_nFoo };
std::vector<Foo> vecFoo;
はコンパイル通るだろ? なら「vectorは、構造体は駄目なんですね」とか言うな。
>>413 構造体でも大丈夫だろ。
比較が必要なら比較のコードを書けばいいし、
クラスでも比較のコードを書かなかったら同じエラーが出る。
struct hoge
{
int a, b, c;
bool operator==(const struct hoge &x) const { return a == a.x && b == b.x && c == c.x; }
bool operator!=(const struct hoge &x) const { return !(*this == x); }
bool operator>=(const struct hoge &x) const { どっちが大きいのか、それは君が決めるしかない }
};
bool operator==(const struct hoge &x, const struct hoge &y) { return x.a == y.a && x.b == y.b && x.c == y.c; }
417 :
391 :2001/05/19(土) 02:12
できればどなたか
>>391 にも引導を渡していただけませんか。
人に言われるまであきらめきれないので・・・
>>417 今どうやって Singleton の実装してる?
>>417 俺にもわからん。
やっぱstaticな初期化メソッドを作って、それを呼んでもらうのが普通だよね。
プロキシ経由でしかアクセスできないことにして、
最初に生成されたプロキシが、
シングルトンのオブジェクトを作るというのはどう?
だけどそんな複雑にしてまで安全を確保する必要性があるのかなぁ。
気持ちはわからなくも無いけど。
420 :
デフォルトの名無しさん :2001/05/19(土) 02:47
Game Programming Gems に載ってた方法だと、こんなのがある。こいつを 継承したクラスのインスタンスを、適当なところで new, delete する。 ---------- template <typename T> class Singleton { static T* m_Singleton; Singleton(const Singleton&); // コピー禁止 public: Singleton() { assert(m_Singleton == 0); int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1; m_Singleton = reinterpret_cast<T*>(reinterpret_cast<char*>(this) + offset); } ~Singleton() { assert(m_Singleton != 0); m_Singleton = 0; } static T& GetSingleton() { assert(m_Singleton != 0); return (*m_Singleton); } }; template <typename T> T* Singleton <T>::m_Singleton = 0; ----------
421 :
391 :2001/05/19(土) 03:00
>>418 一般的なやり方だと思います。いわゆるprotectedメンバに
コンストラクタをおき、次のメソッドのみでオブジェクトを返すような。
Class * Class::instance = NULL; //staticメンバ
Class* Class::getInstance(){
if( instance == NULL ){
instance = new Class;
}
return instance;
}
まさか毎回getInstance( value );ってわけにもいきませんし…
>>419 レスありがとうございます。
> staticな初期化メソッドを作って、それを呼んでもらうのが普通
やはりこれですかね、ただ折角Cから移行してきた所なので悔しくて(笑
また初心者ながらにSingletonをサブクラス化したとき面倒そうかなと。
> プロキシ
なるほど、試してみます。
>>420 すいません、書き込んでて気づきませんでした
これはすごい、ちょっとじっくりみさせていただきます
423 :
デフォルトの名無しさん :2001/05/19(土) 03:13
>>421 私なら条件変数を使わず、ローカル static 変数を使います。これだと
インスタンスを作成するタイミングは明確(初めて関数が呼ばれたとき)
ですが、インスタンスを壊すタイミングが明示的に指定できないので困
る場合アリ。
で、結局
>>420 に行き着くんだけど。
class Class {
public:
static Class& GetInstance()
{
static Class obj;
return (obj);
}
};
#define g_Class Class::GetInstance()
424 :
391 :2001/05/19(土) 03:47
>>420 なるほど、二つ目のインスタンスが作成される可能性をことごとく潰して
いるんですね。しかもテンプレートで使い回しがきき、どんな引数をとる
クラスであろうと対応できると。感動しました、C++にきて良かったです。
>>423 ふーむ、こんなやり方もあるんですね。NULLチェックが省けちゃうとは。
どのみちSingleton使うのは実行時の変更がなさそうなシステム領域のクラスが
多いから壊すタイミングに留意する必要はなさそうですしね。素晴らしい。
初期化なしのSingletonパターン適用クラスを作るときに使わせて頂きます。
識者のご指摘を伺えて今日は幸せでした。レス下さった方々に深く感謝です。
425 :
デフォルトの名無しさん :2001/05/19(土) 04:49
幸せage
426 :
デフォルトの名無しさん :2001/05/19(土) 20:34
class A { void f1(); void f2(); void f3(); }; このクラスにメンバ関数ポインタf0を追加して、 f1、f2、f3をf0を介して呼び出すようにしたいのですが こういうことってどうすれば出来るのでしょうか?
427 :
デフォルトの名無しさん :2001/05/19(土) 21:25
class A { void (A::*f0)(); void test() { f0 = &f2; (this->*f0)(); } };
428 :
426 :2001/05/19(土) 21:47
>>427 その方法でうまくいきました。ありがとうございます。
ですがこうするとエラーになります。
なぜでしょうか?
// コンストラクタ
A()
{
f0 = &A::f1;
}
void main()
{
A* a = new A;
(a->*f0)();
delete a;
}
429 :
デフォルトの名無しさん :2001/05/19(土) 21:57
(a->*a->f0)();
430 :
426 :2001/05/19(土) 22:10
うまくいきました。 何度もありがとうございました。
431 :
デフォルトの名無しさん :2001/05/19(土) 23:16
>>431 3 行とは言わないが、10 行程度にまとめて、論点を明確にせよ。
話はそれから。
434 :
デフォルトの名無しさん :2001/05/19(土) 23:31
>「自作の汎用クラスをその他のクラスでインクルードするのはソース的なまとまりが無くなるような気がする」 気にすんな。 以上。
435 :
デフォルトの名無しさん :2001/05/19(土) 23:44
>>434 同意
C++はクラスをインクルードするのを前提に設計されたのだよ。
コンパイラの都合(性能の話)だそうだ。
どうしても隠したいならラッパーを作るしかないようだ。
>STLをサポートしていない環境
STLのヘッダをインクルードするだけで使えるものもあるが..だめか?
http://www.stlport.org/download.html (SGI風iostream以外は大丈夫だったと思うぞ)
あまり悩むな。
436 :
デフォルトの名無しさん :2001/05/20(日) 00:46
ちょっとお聞きしたいです。 クラスをエクスポートするDLLを作っているんですが、クラスのデータメンバにSTLを用いたものがいくつかあるん です。しかしそれが問題らしく、stringやvectorの変数を宣言する行で警告を食らいます。警告内容はstringやvector をエクスポートしろ、というものですが、これは無視していいんですか?
>>436 DLLってWindowsでしょ?
こんなことしていいの?
リンクするランタイム違っただけで死んでしまわない?
438 :
け :2001/05/20(日) 01:07
typedef list<PROCESSENTRY32> ProcessEntriesList; つー、リストを for_each(pel.begin(),pel.end(),&addProcessEntry); つー、アルゴリズムに void __fastcall TForm1::addProcessEntry(PROCESSENTRY32 pe) を上記のように&渡ししたら動いちゃった・・・ いや、関数オブジェクト書くのがかったるくて適当書いたんだけど、 動いたことに驚いたのは初めて。(動いてて驚くソースは仕事で頻繁に見るけど) これって処理系依存?BCB5なんだけど。
439 :
け :2001/05/20(日) 01:19
追加情報。 addProcessEntry() って関数名だけど、単にリストを順処理させてる関数です。 なんかリスト追加する関数と誤解されそう。 名前付けセンスないなぁ俺。
>>438 どこでも動く、非常に普遍的なコードに見えるっす。
>>438 for_each(pel.begin(),pel.end(),&addProcessEntry);
この行がTForm1のメンバ関数の中にあるなら、
規格の範囲内で、コンパイラには依存しません。
要するに、
this->(&addProcessEntry(pe));
が成立すれば大丈夫ということ。
>>438 「処理系依存」をどう捉えるかによって答えが異なる。
すなわち、「C++ の言語仕様の範囲内」なのか、
「(たとえば)VC でもビルドできる」のか。
前者だとすると(Win32 API な処理系と仮定しても)、
一部分だけ言語仕様から逸脱している。 → __fastcall
後者だとすると(勿論、必要な宣言がすべて正しく揃っているとして)、
「VC でもビルド可能」(たぶん)。
ただし __fastcall は C++ の言語では定義されていないので、
今仮に VC でもビルドできたとしても、
__fastcall な大域関数のアドレスを取得できるかどうかは、
将来の VC でも同じという保証はないと思う。
ちなみに(当たり前のことだけど)、
もし TForm1::addProcessEntry が仮想メンバ関数なら、
たとえその行が TForm1 のメンバ関数の中にあっても、
コンパイルエラーになるはず。
…だよね?
>>441 などなど、もっと詳しい条件が定義されないと、「言語仕様内/外」とか、
「VC でもビルドできる/できない」は、一概には言えないと思う。
443 :
436 :2001/05/20(日) 11:45
>>437 どういうことですか?すいません、まずい理由をもう少し詳しく教えてもらえるとありがたいところです。
>もし TForm1::addProcessEntry が仮想メンバ関数なら、
>たとえその行が TForm1 のメンバ関数の中にあっても、
>コンパイルエラーになるはず。
>…だよね?
>>441 コンパイルエラーにはならないよ。
ちゃんと仮想関数としてコールされるから、
TForm1を継承してaddProcessEntryを書きかえたら、
書きかえたほうが呼ばれる。
__fastcallのことは、すっかり見落としてた(藁。
C++Builder使いなので許しておくれ。
445 :
デフォルトの名無しさん :2001/05/20(日) 17:06
メンバの宣言のとき privateって使ってます? protectedとprivateの使い分けがいまいちわからない。 皆さんの意見を聞かせてください。
446 :
初心者名無しさん :2001/05/20(日) 17:09
とりあえず、C++の入門書読み終えたんですけど 次はどんな本を購入すればいいんですか? 題名、著作者、出版社をできれば教えてください
448 :
デフォルトの名無しさん :2001/05/20(日) 17:13
449 :
初心者名無しさん :2001/05/20(日) 17:27
450 :
デフォルトの名無しさん :2001/05/20(日) 17:44
>>449 「プログラミング言語 C++」はバイブル。C++ でプログラムを組むなら、手元に
置いておかないと話にならない。
7000 円分の価値はあるから、さっさと買え。
451 :
初心者名無しさん :2001/05/20(日) 17:50
>>450 わかりました。
在庫切れみたいなので
デッカイ本屋行って買ってきます
452 :
け :2001/05/20(日) 18:00
>>440 -442
for_each() の実装が
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function f)
{
while (first != last) f(*first++);
return f;
}
だから
(&addProcessEntry)(*first++);
ってやってる事だと解釈したんだけど…
同じ事は C だと(Cと比べるのも問題あることは分かってるけど)
for_each(first,end,addProcessEntry)
と渡しといて、
(*addProcessEntry)(*first++);
で受けるよな〜(確か)と、いう点が疑問なんです。
関数のアドレスに関して、C++ではどういう解釈をすれば良いのかに悩んでいるのが現状です。
関数オブジェクト渡しならば()をオーバーロードしてるから分かるんですが。
そこらへんの解釈を理解するにはARM買って読むしかないのかな?
453 :
デフォルトの名無しさん :2001/05/20(日) 18:57
fileのラッパークラス CFileを作ってと演算子のオーバーロードで file >> MyClass; // load 見たいのをやりたいんですけど、 >> 演算子だと 右辺に新しいクラスが 来るたびに CFileクラス定義に追加しないといけないですよね? グローバル関数で operator >> を定義 するのと MyClass << file; と逆向きにしてMyClass内でoperator<<を定義 するのとどっちがいいかな? 前者は operator>>関数が無数に出来るので、VC++とかのツールで見にくい(探し難い) 後者は 普通の使い方と逆ですよね?? どういう方法がいいでしょうか?
454 :
デフォルトの名無しさん :2001/05/20(日) 19:09
あ、後者は file >> MyClass >> MyClass2 とか、連続して書けないから駄目か
455 :
デフォルトの名無しさん :2001/05/20(日) 20:28
すいません、friendの使い方について教えてください。 class A { classB { int i; }; friend class B; int i; }; これだと問題なしなのに、 class A { friend class B; classB { int i; }; int i; }; これだとfriend宣言が無視されます。エラーは出ません。 同様に、 class A { friend class B; int i; }; class B { int i; }; これも無視されます。 何が悪いのでしょうか? VC++5.0ラーニングエディションです。
456 :
デフォルトの名無しさん :2001/05/20(日) 21:35
>>455 空のクラス宣言を前置せよ。
class B;
class A {
friend class B;
ほげほげ
};
class B {
ほげほげ
};
457 :
デフォルトの名無しさん :2001/05/21(月) 00:08
>>456 アドバイスありがとうございます。
それを試したのですが、
同じようなソースなのに出来る場合があったり、
出来ない場合があったりします。
コンパイラが狂ってるのかなあ?
あとちなみにこういう場合はどうなんでしょうか?
class A {
friend class C;
ほげほげ
};
class B {
class C {
ぼげぼげ
}
ほげほげ
};
458 :
デフォルトの名無しさん :2001/05/21(月) 00:19
Bの中のCは、Bの外(たとえばA)から見るとB::Cになるんでは? class B { public: class C { } }; class A { friend class B::C; }; なら分からんでもない。 しかしキモいなあ。
459 :
デフォルトの名無しさん :2001/05/21(月) 00:28
>>457 クラスのプロトタイプ宣言をしても駄目か?
class A;
class B;
class C;
を先頭に表記。
というか個々に定義して継承するか包含しないか?
460 :
455 :2001/05/21(月) 21:49
>>458 -459
度々お答え申し訳ないです。
>>458 さんの方法でうまくいきました。
クラスのプロトタイプ宣言で class B::C;
と表記出来ればいいんだと思うんですが、こればかりは駄目みたいですね。
納得しました。ありがとうございました。
>というか個々に定義して継承するか包含しないか?
自分がネストしたがるのは、単にデベロッパスタジオのワークスペースのツリーが
見栄えが良くなるからです。それだけ。^^;
461 :
デフォルトの名無しさん :2001/05/21(月) 23:47
const int x = 3; const int y = 3; int hairetu[y][x] = { {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, }; void proc(int x, int y, int **data) { int i, j; for(i = 0; i < y; ++i){ for(j = 0; j < x; ++j){ data[i][j] = 0; } } } int main(int argc, char* argv[]) { proc(x, y, (int**)hairetu); return 0; } ↑このプログラム実行時にエラー出ちゃうのですが 出ないようにする方法教えて下さい。 二次元配列を、 関数の引数として渡す方法が、分からないのです。
>>438 void __fastcall TForm1::addProcessEntry(PROCESSENTRY32 pe);
が静的メンバ関数でないのなら、
for_each(pel.begin(),pel.end(),&addProcessEntry);
は完全に間違っている。
次のような特別バージョンが生成されると考えることができたとしよう。
typedef void (TForm1::*FUNCTION)(PROCESSENTRY32);
typedef std::list<PROCESSENTRY32>::interator INPUTITERATOR;
FUNCTION A_for_each(INPUTITERATOR __first, INPUTITERATOR __last, FUNCTION __f)
{
// 束縛されていないメンバ関数へのポインタからは呼び出せない。this->が天から振ってくることはない。
while (__first != __last) __f(*__first++);
return __f;
}
束縛後のメンバ関数へのポインタの型 というものはない。
関数オブジェクトの最も簡単なものが関数ポインタである。
__fastcallが暗黙にstaticを主張しているとコンパイラが考えるのは突飛だろうか。
次のような特別バージョンが生成される。
typedef void (*FUNCTION)(PROCESSENTRY32);
typedef std::list<PROCESSENTRY32>::interator INPUTITERATOR;
FUNCTION A_for_each(INPUTITERATOR __first, INPUTITERATOR __last, FUNCTION __f)
{
while (__first != __last) __f(*__first++);
return __f;
}
464 :
け :2001/05/22(火) 01:10
>>463 そうなんです、&func が何で関数ポインタ?というのが疑問なんです。
ちなみに、疑問にお答えします。
静的メンバ関数ではありません。
しかし、for_each() はメンバ関数で実行しているので見えてます。
正確には &(this->func) でしたね。
指摘されるまでうっかり忘れてました。
多分この疑問も分かってしまえばな〜んだ、となるでしょう。
>>461 配列が int hairetu[y][x] なのに、どーして
> void proc(int x, int y, int **data)
> proc(x, y, (int**)hairetu);
なんだよっ!
コンパイラの警告を無視するな(したはずだろ?)。
466 :
Rip_Mapiro :2001/05/22(火) 01:57
>>461 template<Temp> //Tempは何らかの二次元配列
void
Proc(int x,int y,Temp data){
//省略
data[i][j];
}
と関数を定義して
proc(x,y,hairetu);
でコール。
本当は板違いだが++なレスで答えたぞ。
467 :
onamae :2001/05/22(火) 02:37
>>465 -466
わいもようわかりません。
こんなかんじだしょか。
#include <iostream>
using namespace std;
const int x = 3;
const int y = 3;
int array[][x] = {
{1, 0, 0},
{1, 0, 0},
{1, 0, 0}
};
template<class T>
void proc(int x, int y, T (*data)[3])
{
int i, j;
for(i = 0; i < y; ++i){
for(j = 0; j < x; ++j){
data[i][j] = 0;
}
}
}
int main(void)
{
proc(x, y, &array[0]);
return 0;
}
>>464 >しかし、for_each() はメンバ関数で実行しているので見えてます。
見えない。for_eachはマクロではない。メンバ関数への
ポインタがthisに暗黙に束縛されることはない。
>正確には &(this->func) でしたね。
不正確だ。束縛された非静的メンバ関数へのポインタは
()オペレータ以外に使えない。
多くの場合コンパイラはthis->を無視するだろう。
>静的メンバ関数ではありません。
その関数に非静的メンバ変数を参照する文を追加するとどうなるだろうか?
確かにstaticでないなら、実装依存というより
マクロ的に実装しているコンパイラの不具合と言えるかもしれない。
>>466 訂正:
template<Temp> -> template<class Temp>
Proc(int x,int y,Temp data){ -> proc(int x,int y,Temp data){
470 :
onamae :2001/05/22(火) 04:30
>469 質問君なわいにもわかりました。ありがとうございます。
471 :
387 :2001/05/22(火) 12:29
どうも、お久しぶり。 で、連想配列(ハッシュ)ですが、C++自体にはないが、 プログラマーの考えでどうにかなる、というものでしょうか?
472 :
デフォルトの名無しさん :2001/05/22(火) 14:45
473 :
>387 :2001/05/22(火) 15:26
だから STL にあるって... 大抵の環境では std::hash_map が用意されてる。 でも std::map でも普通は十分だし、 hash_map の方が遅いケースもある。
474 :
387 :2001/05/22(火) 17:35
了解。
C++標準にstd::hash_mapは存在しない。 SGIのSTL実装には含まれる。
476 :
あたま :2001/05/22(火) 20:29
DirectXを用いてラインからリアルタイムに音波形表示するにあたって何かよい方法ってありますか? MSC++4.0とDirectXSDK8.0なのですが・・・
477 :
デフォルトの名無しさん :2001/05/22(火) 22:41
>>476 DirectX8は、VisualStudio5.0SP3以上じゃなきゃ
駄目じゃなかったけ?
>>466 さん
エラー無しで、完璧に動いてくれましたです。
有難うございますぅ〜
479 :
デフォルトの名無しさん :2001/05/23(水) 00:23
>>478 それじゃ結局多次元配列の使い方はわからないままじゃん。
いーのかそれで。
つっても俺もわからんかった。
これで正解なの?
const int x = 4;
const int y = 3;
int hairetu[y][x] = {
{1, 2, 3, 4},
{1, 2, 3, 4},
{1, 2, 3, 4},
};
void proc(int x, int y, int* data)
{
int i, j;
for(i = 0; i < y; i++){
for(j = 0; j < x; j++){
*data++ = 0;
}
}
}
int main(int argc, char* argv[])
{
proc(x, y, (int*)hairetu);
return 0;
}
481 :
461 :2001/05/23(水) 00:55
>>481 その何でも人に聞こうという姿勢を何とかしようよ。
検索すればすぐに見つかるんだからさ。世の中親切な人ばかりじゃないよ。
485 :
あたま :2001/05/23(水) 01:57
>477さん あれ、そうでしたっけ? そうしたらSDKの7で製作しますがどんなもんでしょうか?
486 :
け :2001/05/23(水) 02:28
>>468 >見えない
それは、呼びもと(もしくは展開元)側では見えても、for_each()内部では見えないはずだ
という意味なのでしょうか?
464はメンバ関数内で別のメンバ関数を見ているのだから見えるという意味で書きました。
>非静的メンバ関数へのポインタは()オペレータ以外に使えない
そ・・・そうなのか。知らなかったです。
やっぱりARM買って読んどかないとまずいかな。
487 :
け :2001/05/23(水) 02:35
>>468 >その関数に非静的メンバ変数を参照する文を追加
フォーム上のリストボックス(当然非静的メンバ変数)に->add()してますから、既に存在してます。
あ、だったら当然に動的メンバ関数じゃなきゃ駄目じゃん。
・・・は、今ごろ理解が進んだ。
そうか、動的メンバ関数なら隠された引数(this)が必要なはずだから、関数ポインタだけ渡しても
呼べるはずが無い。
だから変だと言われていたわけですね。
488 :
け :2001/05/23(水) 03:03
おかしいですね・・・ソースの必要部分載せときます。 コンパイルオプションの警告設定はデフォルト指定の選択モードですが、コンパイル・リンク などのエラーなしです。 // ProcessEntriesList定義 typedef list<PROCESSENTRY32> ProcessEntriesList; // ProcessEntries class ProcessEntries { private: public: ProcessEntriesList& ProcessEntries::getEntriesList(ProcessEntriesList& EntriesList); }; ProcessEntriesList& ProcessEntries::getEntriesList(ProcessEntriesList& EntriesList) { EntriesList.clear(); HANDLE ph = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (ph<0) return EntriesList; PROCESSENTRY32 pe; AnsiString str; pe.dwSize = sizeof(PROCESSENTRY32); Process32First(ph, &pe); EntriesList.push_back(pe); while (Process32Next(ph, &pe)) EntriesList.push_back(pe); CloseHandle(ph); return EntriesList; } // TForm1定義 class TForm1 : public TForm { __published: // IDE 管理のコンポーネント TListBox *ListBox1; TTimer *Timer1; void __fastcall Timer1Timer(TObject *Sender); private: void __fastcall addProcessEntry(PROCESSENTRY32 pe); // ユーザー宣言 ProcessEntries pe; public: // ユーザー宣言 __fastcall TForm1(TComponent* Owner); }; // メンバ関数 void __fastcall TForm1::addProcessEntry(PROCESSENTRY32 pe) { AnsiString str; ListBox1->Items->Add(str.sprintf("%d : ",pe.th32ProcessID) + pe.szExeFile); } void __fastcall TForm1::Timer1Timer(TObject *Sender) { ListBox1->Clear(); ProcessEntriesList pel; pe.getEntriesList(pel); for_each(pel.begin(),pel.end(),&addProcessEntry); }
489 :
デフォルトの名無しさん :2001/05/23(水) 03:34
まだC++の勉強始めて4日ぐらいなんですけど、Cに比べて機械語との 対応関係が見えにくいってことはないですか? 慣れればそんなことない んかな。っていうか、そんなこと考えるような時代じゃないのか?
ttp://www.csc.titech.ac.jp/~j91831/document/callback.html なるほど。確かに、addProcessEntryは、普通のメンバ関数ではなかったのだ。
addProcessEntryは、__fastcall指定によって、
こっそりとレジスタからthisポインタを取り出し、あたかもメンバ関数のように動作する。
コンパイラからは、普通の関数、静的メンバ関数に見えるに違いない。
この動作は、TForm1ポインタをコンストラクタ引数に取る関数オブジェクトを使用するのに似ている。
__fastcall指定がほとんど決定的で、__fastcallを使っている以上、
そのテクニックを使っても当然だという人もいるだろう。
ちなみに、VC++では、__fastcallにこれほどの意味はなく、もちろんエラーとなる。
>>489 見えにくいだけで、見ることは出来る。
むしろ、オブジェクト指向言語の中で、
最も「マシン語コードがどうなるか丸見え」のはC++。
C言語しか使ったことがない人は、
動きが把握できなくて不安になるかもしれない。
それは単に新しい言語だから知らないことが多いというだけで、
わかってみれば大した事は無い。
492 :
け :2001/05/24(木) 00:21
>>490 メンバ関数とはいえ、addProcessEntry()はコールバック関数ではないので、
オブジェクトインスタンスは存在しないはず・・・
こ、こりはもしかしてEAXレジスタのゴミ(この場合thisポインタ)が偶然に効いて
実行できたという話でしょうか?(呼び元のTimer1Timer()はコールバック関数だけど)
>>492 addProcessEntryもTimer1Timerも静的メンバ関数という意味で
コールバック関数であり、メンバ関数ではない。
もはや君に言うべき言葉を見つけられない。
addProcessEntryは静的メンバ関数である。
暗黙にthisポインタを使用することができることがまさに
非静的メンバ関数であると主張できるが、コンパイラが
そうとは思っていない以上、さらに、__fastcall指定が
存在していることから、非静的メンバ関数ではない。
何度でも言うがaddProcessEntryは静的メンバ関数である。
494 :
け :2001/05/24(木) 19:12
>>493 静的メンバ関数か否かは突き詰めればthisポインタ参照可能か否かに左右されるの
では無いのですか?(もしくはthisポインタ参照不要)
どう実装しているかは関係ないと思われますが。
現に静的メンバ関数にしてしまうと、当然に
E2231 メンバー 'member' はオブジェクトなしでは使用できない コンパイラエラー
が発生してコンパイルできません。
というようにコンパイラは非静的メンバと認識しています。
以上から__fastcall宣言は静的メンバ関数とは無関係な宣言と思われます。
>>494 それは私の言ったことを逆から言っているように見える。
私は、束縛なしに利用できるのだから静的メンバ関数に違いないと主張する。
束縛なしに非静的メンバ関数へのポインタを使用できるなら不正である。
これがメンバ関数ではないことを証明するかどうかは確かに不明瞭のように見える。
しかし、考えてほしい。もし正確にメンバ関数ならば、__fastcall指定がなぜ必要なのか?
束縛なしに利用できるなら、その関数へのポインタは、文字通り静的である。
そこで表現を和らげ、実装として静的メンバ関数である、というのは同意できると考える。
実際、これは水掛け論のように思える。__fastcall指定の存在自体がそれを暗示する。
ここで質問に答えなければならない。
__fastcallゆえ、Timer1Timerを呼ぶ際に、thisポインタがレジスタへプッシュされる。
その中で、for_eachに、ある関数へのポインタを渡す。
ある関数へのポインタは、__fastcallゆえ、残っていたthisポインタをそれが何かを気にせずポップして使用する。
これはTimer1Timerから呼ぶ以上、レジスタにたまたま残っているわけではないので、
実装として完全に正しいだろう。
言語としては、束縛なしに非静的メンバ関数へのポインタを使用することは不正である。
496 :
け :2001/05/25(金) 01:17
>>495 >これはTimer1Timerから呼ぶ以上、レジスタにたまたま残っているわけではないので
なるほど。最適化のせいとすればゴミとは意味が変わってきますね。了解しました。
しかし、__fastcallのせいとも言えないのではないかという状況になってきました。
以下のコードを見てください。
これがBCBだと何故かやっぱり動いてしまうんです。
#include <stdio.h>
#include <list.h>
#include <algorithm>
typedef list<int> IntList;
class ForEachTest {
IntList il;
public:
ForEachTest() {
for ( int i=0 ; i<10 ; i++ ) {
il.push_back(i);
}
}
void PrintList(int i) {
printf("%d\n",i);
}
void DumpList() {
for_each(il.begin(),il.end(),&PrintList);
}
};
int main(int argc, char* argv[])
{
ForEachTest fet;
fet.DumpList();
return 0;
}
ちなみに手元のUNIX機では当然にコンパイルできません。
bash-2.02# g++ -v
cc -v
gcc version 2.7.2.1
bash-2.02# g++ ForEachTest.cpp
/usr/include/g++/algo.h: In function `void (ForEachTest::* for_each(class list<int>::iterator, class list<int>::iterator, void (ForEachTest::*)(int)))(int)':
/usr/include/g++/algo.h:65: warning: argument passing to `ForEachTest *' from `int' lacks a cast
/usr/include/g++/algo.h:65: too few arguments to function
経緯はともかく結論として、&addProcessEntryをfor_each()に渡すのは、やっぱり
怪しすぎるコードである。
ということだけは間違いないですね。
intel系のアセンブラコードを読めれば、BCBの謎は解明できると思うのですが、私は読めないので
どうにもお手上げです。
>>496 なるほど私は、ただ踊らされているだけのようだ。
addProcessEntryは__fastcall指定のコンパイルオプションが
あったとしてもメンバ関数である。
だが依然として、実装として静的メンバ関数であることは
それほど間違っていないと言う。
私は__fastcall指定をなくすコンパイルオプションがあると信じるが、
for_each(pel.begin(), pel.end(), &addProcessEntry);
を許してしまうのは、明かにそのようなコンパイラの不具合と断言でき、
thisポインタをレジスタを介して渡すメカニズムのために、たまたま動く。
498 :
デフォルトの名無しさん :2001/05/25(金) 05:10
OS(Linuxとか、Winとか*BSDとかOSX)って、C++でかけるのかな。 すくなくとも、Linux はCでしょ。
Beは++らしいでぇ
500 :
デフォルトの名無しさん :2001/05/25(金) 11:19
class A、struct Bがあったとして、 Aのメンバ関数の返り値にBを使いたいんだけど BのメンバにAも入れたい・・・ どうすればいいんでしょ??
>>500 struct B;
class A {
struct B *hogehoge();
};
struct B {
A foobar;
};
502 :
デフォルトの名無しさん :2001/05/25(金) 14:07
> v(^・^)v 殺したい。
設計をみなおす。相互参照は少ないほどよい。 どうしても必要であれば、「前方宣言」で調べてみるべし。
>>504 それで設計見直してたらオブジェクト志向
の精神からはずれてしまうと思われ
>>498 一部がインラインアセンブラになるくらいで書けます。
C++でRTOSを自作したことはあるから、
あとはこれの規模を大きくするだけです。
BeOSもC++じゃなかったっけ?
またWindowsNTのモジュールの多くはC++です。
カーネル部分は知らないけど。
507 :
け :2001/05/26(土) 01:59
>>497 >なるほど私は、ただ踊らされているだけのようだ。
そう感じられましたら申し訳ありませんでした。
ただ、言われたことを鵜呑みにしても仕方が無いですから、自分でも調べられる
ことは調べて、それでも分からないこととか、見落としている点、勘違いしている
点を指摘してもらう。
そんな意図で色々と書いたりしています。
thisポインタの問題など、ためになる情報は非常にありがたいです。
できましたら、また疑問が浮かんだときには、ご協力願います。
>>505 うーん「ソフトウェアが表すもの(オブジェクト)が相互参照しているなら、
ソフトウェアも相互参照するべきだ」という主張なんだよね。
その主張自体はもっともだと思うけど、その理由"だけ"で相互参照を許すのは
あまり良くないと思うよ。
相互参照によって起こりやすいモジュール密結合の問題点をしっかり認識した
うえで採用するなら、もちろん何の問題もありません。
最終的な目標は良いソフトを作ることであって、オブジェクト思考や相互参照
の排除はそのガイドラインのひとつだよね。それぞれのガイドラインが相反する
としたら、それぞれの長所短所を比較してバランスをとる必要があると思うのね。
505氏はわかっているだろうけど、初心者が見て相互参照の問題点を理解せずに
「オブジェクト思考でOKだから、相互参照はOKなんだ」と思うと良くないと
思うので、意見しておきます。
509 :
509 :2001/05/27(日) 19:43
Visual C++でプログラミングを始めた者です。 coutで指数表記を使う場合、3.15e+004のように指数部が3桁で表示されてしまいます。 これを指数部が2桁になるように書式設定することは可能でしょうか? マニュアルにはなさそうだったのですが、ご存知の方はお教え願います。
510 :
け :2001/05/27(日) 20:30
511 :
け :2001/05/27(日) 20:31
あ、指数部?失礼、間違えた。
512 :
509 :2001/05/27(日) 20:40
はい、「3.15e+04」のように表示したいのです。 仮数部であれば、cout << setprecision(n); ですね。 << をオーバーロードするしかないのでしょうか。
513 :
デフォルトの名無しさん :2001/05/31(木) 20:05
delete[] a; ってどーゆーこと? deleteが拡張されてるの? どんな定義がされているとこーゆー使い方できるの?
>>513 配列をnewで構築したときはdelete[]で破壊すべし。
例)
new a = int[100];
:
:
delete[] a;
激鬱 int* a = new int[100]; イッテクル
>>514 ,515
なんか別の言語でそんな表記するのかと思ったYO!
517 :
G-4 :2001/06/01(金) 11:53
ネットワーク上に共有されているCD-Rドライブや、 MOドライブの状態(読み込み中、待機中、開閉状態等々) が分かるような簡単なアプリを作ろうかなと思ってるんですが、 どんな風にすればいいですかねぇ? アイデア下さい。
518 :
Install :2001/06/01(金) 13:58
本を探しています。 Install Shield For Visual C++6.0 大沢文孝/著 ネットサーブ/監修 出版社 アスキー 価格 3400円(税抜き) 新宿近辺で見かけた方いませんか???
519 :
デフォルトの名無しさん :2001/06/01(金) 14:15
520 :
デフォルトの名無しさん :2001/06/01(金) 14:47
c++でプログラミングしたいですと、javaが好きな先生に言った。 オブジェクト指向が分かんないと意味ないから、始めにjavaを勉強して、 そのあと、オブジェクト指向が分かればc++、分からなければCにすればと言われた。 そんな感じでしたが、皆さんどう思われ?
>>517 C/Sにするのが一般的。
S側でデバイスを監視するデーモンを起動しておいてCでリモート。
523 :
デフォルトの名無しさん :2001/06/02(土) 19:39
vcでstringに+演算子が無いんだけど、なんで?
525 :
a :2001/06/02(土) 20:35
C++全然わかりません。 +演算子って一時オブジェクトを作って返す?あってる? じゃあそのオブジェクトの寿命はいつまで? 例えば MyString a, b, c; a = b + c; b + cの部分で一時オブジェクトが作られるの? a に代入するまでそれは生きてるの? 試してみたら不正な処理って出るんですけど。 誰かおしえてくださいませ。
>>524 粘着だね。アンチMFCキティ君(w
ここは荒らさないでね。
>>525 C++では演算子の挙動も自分で記述できる。
そのクラスの演算子がどう定義されているか調べて見れ。
527 :
デフォルトの名無しさん :2001/06/02(土) 20:43
MyStringがどういうものだわからないけど ちゃんと代入演算子定義した?
申し訳ない。
>>526 の方が正確だわ
代入演算子だけでなく他の演算子(
>>525 の例だと+演算子)
が必要。(かどうかはMyStringによるが・・・)
529 :
a :2001/06/02(土) 20:53
>>527 たぶんちゃんと定義したと思うんですが。
MyString &operator=( const char *string);
MyString &operator=( const MyString &string);
こんな感じの代入演算子は作りました。動作確認済み。
んで、+演算子は
friend MyString operator+( const MyString &left, const MyString &right);
なんですけど。
デストラクタでprintfしてみたら代入前に解放してる?
コピーコンストラクタは?
531 :
a :2001/06/02(土) 21:00
533 :
デフォルトの名無しさん :2001/06/02(土) 22:42
ひらに失礼
535 :
a :2001/06/02(土) 23:04
あ! MyStringを受取る方のコピーコンストラクタの定義が無かったです。 定義したらちゃんと動きました、ありがとうございます >ALL で、+演算子は一時オブジェクトを返すってのは正しいのでしょうか?
>+演算子は一時オブジェクトを返すってのは正しいのでしょうか? 正しくありません。 返すのは一時オブジェクトのコピーです。 最適化のされかたによっては一時オブジェクトは 作成されないかもしれませんが、その辺は私も あまり詳しくありません。
537 :
ミトコンドリ子 :2001/06/03(日) 01:08
>>535 Effective C++, More Effective C++を読むとここらへんの理解は進むわよ。
でも自分で簡単なテストプログラムを書いて自分で確かめてみるべきだと思うわ。
コンストラクタ、デストラクタ、コピー、代入の各関数にプリントを入れてみて
動作を追跡してみたらどうかしら。
>>535 よかったな。がんばれよ。
こういう向学心に燃える奴にならいくらでも協力してやるんだけどなぁ。
課題丸投げ厨に爪の垢煎じて飲ませてやりたいよ。
539 :
デフォルトの名無しさん :2001/06/05(火) 14:33
こんにちは。C から C++ に移行しつつある者です。 クラスの中に、関数 func と、関数へのポインタ *myfunc を定義して、 C 言語ライクに myfunc=func と記述したところ、エラーがでます。 具体的には、 #include <stdio.h> class Hoge{ public: double func1(double a){fprintf(stdout,"hoge\n");}; double (* myfunc)(double); void setfunc(void){ myfunc = func1; } }; というソースをコンパイルすると、 no matches converting function `func1' to type `double (*)(double)' candidates are: double Hoge::func1(double) てな感じでエラーがでるのです。 myfunc が func1 を指すようにしたいのですが、 C++ ではどの様に記述すればいいのか、お教え頂けないでしょうか?
540 :
ミトコンドリ子 :2001/06/05(火) 15:22
結論から言うと、できないわ。 double Hoge::function( double ); (メンバ関数) と double ::function( double ); (グローバル関数) は違うものよね。 そしてfunc1は前者だし、myfuncは後者を指すポインタを表している。 なのでコンパイラがエラー報告しているわけ。 myfuncの定義をメンバ関数へのポインタに修正してあげれば良いわ。 class Hoge { double (*Hoge::myfunc)(double); public: double func1(double a); void setfunc(void) { myfunc = func1; } double callfunc(double a ) { return( (this->*(myfunc))(a) ); } ... }; とすれば通ると思うわ。 でも、C++で関数へのポインタを使いたくなったときには一度立ち止まって考えてみて。 仮想関数を使うほうが、アナタのやりたいことを効率的で型安全で保守性を保って 行うことができることが多いわよ。 がんばってね。
double (*Hoge::myfunc)(double); でなく、 hoge::*myfunc でそ
542 :
デフォルトの名無しさん :2001/06/05(火) 16:26
VC++ではOKだけど G++ だと アドレス代入の行 myfunc = func1 で warning : assuming & on `Hoge::func1' ってなwarningが出るんですが、 消すにはどうしたらいいんでしょう?
>>542 myfunc = &func1; にすればいいんじゃないかしら。
でもそれはエラーメッセージを読めば想像がつかないかしら?
545 :
ミジン子 :2001/06/05(火) 16:43
すいません、G++使い始めたばかりで英語メッセージわからないんです 辞書引いたら assumingって でしゃばったって意味なんだけど どういうことなんでしょ? VC++だと & つけるとエラーが出ます G++は 有っても無くても動く。なぜぇぇぇぇ???
>>545 辞書は assume で引いたほうがよいかと。「仮定する・推量する」
547 :
ミジン子 :2001/06/05(火) 17:48
Thanx。VC++だと 仮想関数のアドレスを取ろうとしました ってエラーなのは なんでかなぁ、、、どっから仮想関数が出てくるんだ?
548 :
539 :2001/06/05(火) 19:19
皆様レスありがとうございます。 以下のソースで g++ でコンパイル&実行ができました。 (VC++ は手元にないのでちょっと確認できません。) 仮想関数の方が良い、という御指摘ですが、 それはこれから勉強して行きたいと思います。 #include <stdio.h> class Hoge { double (Hoge::*myfunc)(double); public: double func1(double a){return a;}; void setfunc(void) { myfunc = &Hoge::func1; } double callfunc(double a ) { return( (this->*(myfunc))(a) ); } }; int main(){ Hoge hoge; hoge.setfunc(); fprintf(stderr,"%lg\n",hoge.callfunc(1)); }
549 :
デフォルトの名無しさん :2001/06/05(火) 19:32
ちょっと相談です。 Windowsでラップクラスを作ってるんですけど・・・ やってる事を一言で言えば GetWindowLongとSetWindowLongでインスタンスのポインタを保存して メンバ関数をプロシージャのようにしています。 このクラスはHWNDに関わるAPIをラップした基本クラスから派生させています。 ちょっと長いですが。 class CBaseWnd{ private: m_hWnd; public: CBaseWnd() : m_hWnd(NULL){} virtual LONG GetWindowLong(int nIndex){ return ::GetWindowLong(m_hWnd, nIndex) } virtual LONG SetWindowLong(int nIndex, LONG dwNewLong){ return ::SetWindowLong(m_hWnd, nIndex, dwNewLong) } }; class CRegistWnd : public CBaseWnd{ private: static CRegistWnd* m_lpThis; static LRESULT _WrapWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { /* 最初のメッセージ受信時はm_lpThisの値を::SetWindowLong(hWnd, 0, (LONG)m_lpThis)で格納*/ /* 以後はGetWindowLongでインスタンスのポインタを取得し、MainWndProcメンバ関数を呼ぶ*/ } LRESULT MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) = 0; public: ATOM RegisterClassEx( /* 省略 WNDCLASSEXの値を引数で*/) { /* 内部でWNDCLASSEXに値設定&登録、その際cbWndExtraにはsizeof(CRegistWnd*)を入れている*/ /* プロシージャとしては_WrapWndProcを登録 */ } HWND CreateWindowEx( /* 省略 CreateWindowExの引数と同等*/ ) { /* ::CreateWindowEx実行 m_lpThisにthisを入れておく*/ } }; 相談内容につづく
550 :
549 :2001/06/05(火) 19:33
上記CRegistWndを使って自己登録ウインドウを作成するクラスにしようと思っています。 この時、cbWndExtraをインスタンスの保存で使っているので、上記クラスを使用する場合 このままではcbWndExtraを利用できません。 そこで、CRegistWndのRegisterClassExの引数としてcbWndExtraの値を設定可能にするために この関数の内部で、引数で指定されたcbWndExtra + 指定のcbWndExtraの値 + sizeof(CRegistWnd*) のようにポインタ分のメモリをを内部で余計に取るようにします。 そして、SetWindowLong等をこのクラスから普通の感覚で使えるようにするために SetWindowLongとGetWindowLongをオーバーライドして、 nIndexの値が正の数の場合に、指定された数よりsizeof(CRegistWnd*)を足して 外見上ほぼ同等の動作をさせるようにしました。 このようなクラス設計はダメダメな設計でしょうか? 実際にこのクラスを使う場合、CRegistWndからさらに派生して使う事になるのですが、 その時にSetWindowLong等をオーバーライドして違う動作をさせた場合に 問題が発生する可能性があります。 オーバーライドした物の内部でCRegistWnd::SetWindowLongを 呼び出してくれれば良いのですが、人にこのクラスを使ってもらう場合 直接::SetWindowLong等を呼び出してしまうかもしれません。 習慣的には同等の動作をさせる場合は、出来るだけ派生元クラスの関数を 呼び出すものかとは思うのですが・・・ どなたかご教授お願いします。
551 :
ウツダシノウ :2001/06/05(火) 21:00
メンバ関数のポインタの話 の続きなんですが、クラス外からの呼び出し方法についてなんですが class hoge{ public: void (hoge::*pFunc)(); hoge(){ pFunc = func; } void func(){printf("omaemona" ); } } とこんな感じでポインタに入れたのをメイン関数から呼ぶのどうすればいいんでしょう? main(){ hoge instance; (instance.*pFunc)(); } かとおもったら pFuncが定義されないってエラーがでます
552 :
デフォルトの名無しさん :2001/06/05(火) 21:03
>>551 pFuncが定義されてないんじゃない?
初期化してない普通のポインタ使おうとしてもそうなるでしょ?
>>551 >void (hoge::*pFunc)();
「hoge::」いらないんじゃない?
555 :
ウツダシノウ :2001/06/05(火) 21:28
あぁ .*演算子の右辺は左辺のメンバにアクセスするのと違うんですね よく考えたら当たり前 (instance.*instance.p)() でokでした。でもなんか間抜け。もっとダイレクトにかけないのかしらん
556 :
ウツダシノウ :2001/06/05(火) 21:30
>>554 ちょっと上に出てるけど、クラス内のメンバ関数のポインタの場合は必要です
いらないのは C の場合(後staticメンバ関数の場合)
C++で関数へのポインタが必要なときは、 設計を間違えたときだけ。
すみません、Cのランタイムや生のDLLを呼ぼうとしてました。 これからはSTLやCOMを使いますので許してください。
561 :
デフォルトの名無しさん :2001/06/06(水) 17:41
こんにちは。昨日に引続き、C から C++ に移行しつつある者です。 new 演算子で、二次元配列を確保する方法に関して質問です。 C の malloc の様に、動的に二次元配列を確保する際、 配列サイズを変数 NX、NY で制御したいのですが、うまくいきません。 具体的には、以下のようなソースのコンパイルに失敗します。 class Pixel{ public: int v; Pixel(int i=0){v=i;}; }; class Image{ public: int NX,NY; Pixel **p; Image(int myNX=1,int myNY=1){ NX=myNX; NY=myNY; Pixel (*p)[NY] = new Pixel[NX][NY]; }; }; NX、NY ではなく、具体的な数でやれば成功するのですが、 NX、NY を用いて確保したいのです。 ご存知の方はお知らせ頂けないでしょうか?
>>561 そりゃCからC++に以降以前の問題。
mallocでも無理だろう。
Cの基本部分すら理解していないようなので、一からやり直すべし。
563 :
561 :2001/06/06(水) 18:10
>>562 malloc 使えば、
p = (Pixel **)malloc(sizeof(Pixel *)*NX);
for(i=0 ; i<NX ; i++){
p[i] = (Pixel *)malloc(sizeof(Pixel)*NY);
}
で、できますが…。
>>563 それなら、
p = new Pixel*[NX];
for(i=0 ; i<NX ; i++){
p[i] = new Pixel[NY];
}
とすればよいだけのような...。pは2次元配列なのか配列へのポインタなのかはっきりすべし。
誰か「Pixelをクラスにするのはやりすぎだよ」って 教えてあげれば良いのに。
>>561 2次元配列なんか不要。
ポインタの配列のぶんだけメモリ消費量も激しいし、速度も遅くなる。
#include <vector>
using namespace std;
class Pixel {
int v;
public:
Pixel(int i=0) : v(i) {}
int Set(int c) { return v = c; }
};
class Image
{
private:
int NX, NY;
vector<Pixel> m_Pixel;
public:
Image(int myNX = 1, int myNY = 1)
: NX(myNX), NY(myNY), m_Pixel(myNX*myNY)
{
}
Pixel &Dot(int x, int y) { return m_Pixel[y * NX + x]; }
};
Image img(50, 50);
img.Dot(10, 10).Set(crRed);
マイナー次元の要素数が決定していないと 多次元配列にはアクセスできないよ。 NX*NYの1次元配列として確保して Pixel[myNX*NY+myNY]とかしないとダメ。
>>561 論点ずれるけど2次元配列なんか使うより、
フラットに使った方がスマートでないかい?
[ ][ ]は使えないけど。
class Image {
int NX, NY;
public:
Pixel *p;
Image(int myNX=1,int myNY=1) : p(new Pixel[NX * NY]) {};
Pixel operator()(x, y) { return p[x * NY + y; };
};
NYを2の倍数にすると吉。
569 :
561 :2001/06/06(水) 19:57
>>565 Pixel は例えでして、本当は、2次元格子上に細胞モデルを配置した
数学モデルを考えています。ただ、逆に混乱させてしまったかも知れません。
>>566 一次元配列を二次元にマップするのはわかりましたが、
vector<Pixel> の部分 (テンプレート?) がまだ勉強不足で
わかりませんので、今晩検討してみます。
571 :
561 :2001/06/06(水) 19:59
再び 561 です。 569 を書いている間に、さらに 2 人の方のレスが。 ありとうございます。 みなさん一次元配列を使うべし、というところは 共通しているようですね。試して見ます。
>>568 ブラケットどうしても使いたいのであれば、
template <class T> class CArray2D { // エラーチェック省いてます
T** pptAry;
public:
CArray2D(void) : pptAry(NULL) {}
~CArray2D() { Free(); }
operator T**() { return pptAry; }
void Alloc(int nWidth, int nHeight) {
Free();
pptAry = new T*[nHeight];
pptAry[0] = new T[nWidth * nHeight];
int nY;
for (nY = 1; nY < nHeight; nY++)
pptAry[nY] = pptAry[0] + nY * nWidth;
}
void Free(void) {
if (pptAry != NULL) {
if (pptAry[0] != NULL) delete[] pptAry[0];
delete[] pptAry;
pptAry = NULL;
}
}
};
というテンプレートクラスを作って、
CArray2D<Pixel> aPixel;
aPixel.Alloc(16, 16);
aPixel[0][0].Set(...);
とか。
>>572 そこまでして[]を使う意味があるの?
(x,y)でええやん。
あとC++では0をdeleteしても大丈夫です。
だから無効なポインタには0を入れましょう。
処理系によってはNULLが0ではない可能性があるので、
NULLは使わないようにしましょう。
574 :
568 :2001/06/07(木) 00:08
>>572 サンクス。
列分の配列が増えちゃうね。下でどうだ。
#オペレータオーバーロード萌え〜
template <class T> class Array2D {
const int rawWidth;
T* array;
struct Raw {
T* raw;
Raw(T* nRaw) : raw(nRaw) {};
T& operator[](int x) { return raw[x]; };
};
public:
Raw operator[](int y) { return Raw(array + y * rawWidth); };
Array2D(int w, int h) : rawWidth(w), array(new T[w * h]) {};
~Array2D() { delete[] array; }
};
int main() {
Array2D<Pixel> aPixel(16, 16);
aPixel[0][0].Set(1);
return 0;
}
>>574 そこまでやるなら、いっそのこと2次元イテレーターとかを作って、
汎用コンテナにしてはどうか。
X方向にY=3でソートとかできると便利かも。
576 :
568==574 :2001/06/07(木) 00:15
>>573 >そこまでして[]を使う意味があるの?
>(x,y)でええやん。
普段Java好きだから同意。
けど2次元配列使ったソースをコンパイルし直すだけで、
リユースできれるから無意味でもないと思う。
> あとC++では0をdeleteしても大丈夫です。
> だから無効なポインタには0を入れましょう。
そうだったのか。
コンパイラに起こられるからではないのですね(Javaちゃうって)
> 処理系によってはNULLが0ではない可能性があるので、
> NULLは使わないようにしましょう。
それはどこかの馬鹿がどこかで
#undef NULL
#define -1
とかしているのでは?
0で良いは同意だけどNULLでも悪かないでしょ?
#include <stdlib.h>とかすれば
>>573 内部では0では無い事が、多々ありますが、
Cの中では、NULL==0は保証されてたと思いますよ。
576さんが言われるとおり、誰かが0以外にしない限り…。
>>576 ANSI規格で、0のdeleteが安全であることは保障されています。
一方、NULLが0であることは保証されていません。
それだけのことだよ。
579 :
デフォルトの名無しさん :2001/06/07(木) 01:16
CはNULL==0は保証されていないけど C++はNULL==0が保証されてるんじゃなかったっけ? 間違ってたらスマソ
>>ALL NULLの話をすると長くなりそうなので、やめませんか?
581 :
デフォルト引数について質問です :2001/06/07(木) 01:37
#include <string> using namespace std; void f(string p1, string p2); の関数にデフォルト引数を設ける場合、 void f(string p1 = string(), string p2 = string()); という書き方ではまずいでしょうか? VC++ だとコンパイルエラーになりした。GCC g++ だと コンパイルエラーになりませんでした。
>>581 まずくないです。
ANSI準拠のC++なら通ると思います。
#include <string> のstringで引っ掛かったのでは?
>>582 最近おとなしいね。アンチMFCキティ君(藁
586 :
デフォルト引数 :2001/06/07(木) 02:04
>>582 ありがとうございます。言語仕様上問題無いという
裏付けが中々見つからず、頭を痛めておりました。
>>583 string型でないケースでも同様でした。例えば、
class T{
public:
T();
};
void f1(T p1 = T(), T p2 = T());
→ error C2062: 型 'class T (__cdecl *)(void)' は不要です。
というエラーになります。(VC++)
ただ、
void f1(T p1, T p2 = T());
はコンパイルエラーになりませんでした。(VC++)
>>586 こういうときはANSI準拠に依存する必要があるかどうかをまず十分に検討せよ。
>>587 > こういうときはANSI準拠に依存する必要があるかどうかをまず十分に検討せよ。
というのはなんだかなあ…。
C++の問題かVC++の問題かを切り分けるべきだろう。
VCのANSI対応云々は荒れるからここではおいとくとして、 そのデフォルト引数の使い方はどうかと思うけどな。 関数呼び出しがヘッダ側にあるというのはどうにも保守しにくそうで。
例外処理について200字以内で簡潔に説明してください。 これがわかるほどの人はここにはいないか〜
590が課題でないことを200字以内で簡潔に説明してください(5点)。 人にたよって課題を終わらせようとする590が、将来真人間になる 可能性を200字以内で簡潔に説明してください(95点)。
>>591 - 593
わからないならレスをつけないでくださいよー
この板バカばっかりでだめいたなのかもね こんなとこで得られるものなんてなにもないなー
>>590 例外処理: C++では例外はthrowしてcatchする。
>>590 みんなを煽って宿題をやらせようとしているヴァカ
もしくは相談室を何か違うものと勘違いしているヴァカ
>>598 できないならできないと素直にいえよー
だいたい宿題だとしても人にやってもらって何が悪いんだ
おまえだってできない仕事を人に押し付けてるくせに
>>601 おまえがだろー
わかんないっていえよー
おらー
>>600 だいたい宿題だとしても人にやってもらって何が悪いんだ
本気でそう思ってるの?
授業料どぶに捨てるのも個人の自由と言われれば何もいえないけど。
レベルの低い罵りあいだな(藁
例外処理くらいgoogle一発だと思うが 小学校で辞書の引き方を習わなかったんだろうな 登校拒否のヒッキーの末路か……
例外処理 C++ではthrowとcatchを使う。 throwを実行するとcatchに飛ぶ。goto文の変種である。 gotoと違って他の関数に飛べる。 滅多に使われないから例外処理と呼ばれている。
今まで僕の中でもやもやとわだかまっていたものがすっきりとしました 606サン本当にありがとうございました。
>>603 個人の自由じゃないです。
他人に宿題やらせて卒業して社会人になると社会全体が迷惑しますから。
>>610 おまえの存在自体が社会の迷惑なんだよ
高卒がー
元気だね、課題丸投げ厨。 2ch読んでるヒマあったら勉強しろこのクソガキが。
>>612 かよわい妹の宿題を手伝ってくれないなんて。。。
おにいちゃんのいじわる。。
>>594 >わからないならレスをつけないでくださいよー
同じ事を同じスレで言いたくないから、
>>593 と言ったのだ。
誤爆。
×614
○613
スマソ
>>614 鬱氏
617 :
デフォルトの名無しさん :2001/06/08(金) 08:42
Singletonパターンを、全てのメンバ変数やメンバ関数をstaticにする事で代用する事は可能ですか?
>>617 オブジェクト指向における再利用のためのデザインパターン 第3版より
「Singletonパターンと同等の機能を提供する別の方法として、
クラスオペレーション(C++における静的メンバ関数、Smalltalkにおけるクラスメソッド)を
用いることもできる。しかし、このような言語上のテクニックで対処する方法では、
クラスのインスタンスを1つ以上に変更する場合に困難にになる。
さらに、C++における静的メンバ関数は仮想関数にすることができないので、
サブクラスにポリモルフィックにオーバーライドすることはできない。」
class A; ← Singleton
class B : public A;
A a;
B b;
Aは1つ、Bも1つ、AとBは共存、としたい場合にどうよ。
619 :
デフォルトの名無しさん :2001/06/08(金) 10:52
>>617 やってみて、出来たら出来る。
出来なかったら、出来ない。
620 :
デフォルトの名無しさん :2001/06/08(金) 11:53
>>618 class Bの書き方に気をつけないと、Singletonじゃなくなるぞ
Singletonパターンを作りたい場合は基本的に継承禁止にすべきだと思うが
621 :
デフォルトの名無しさん :2001/06/08(金) 13:23
C++でクラスのコンストラクタにつけることができる、 explicit修飾子が良くわかりません。 一応、MSDNの日本語解説は読んでみたのですが、 引数の暗黙の型変換は一切ゆるしませんという宣言と思 えばよいですか?
622 :
デフォルトの名無しさん :2001/06/08(金) 14:19
SLTのコンテナをヒープに作ることはできますか?
623 :
617 :2001/06/08(金) 15:07
>>618 良くわかりました。どうもありがとうございます。
>>620 >Singletonパターンを作りたい場合は基本的に継承禁止にすべきだと思うが
実装を複雑にして流用しやすくするか、
流用できなくてもいいから実装を単純にするか、
それは状況に応じて選べばいいと思う。
staticメンバ関数でやるというのも一つのやり方だろう。
>>621 explicit修飾子の機能的な面に目を奪われているようだね。
暗黙の型変換についてよく考えてみよう。
この機能は、何が良くて、何が悪いのか、
まだよくわかってないんじゃないか?
理解できれば、explicitの使い方は教わらなくても自然にわかるようになる。
>>622 できます。
vector<int> *p = new vector<int>();
vector<int> *p = new vector<int>(16);
vector<int> *p = new vector<int>;
だけど、こんなのgotoより使わないだろ。
何かのクラスのメンバにいれておけばいい。
class A
{
vector p;
};
コンテナは何がしかのクラスがきっちり管理しておくべき。
コンテナの責任者は誰なのか明確にしておかないといけない。
複数のクラスが共同で管理しようとすると破綻するよ。
625 :
デフォルトの名無しさん :2001/06/11(月) 12:50
「この機能」は「暗黙の型変換」をさしているのですか?
>>625 explicitの機能を指してるのかと思われ。
627 :
デフォルトの名無しさん :2001/06/11(月) 13:03
鉄則:explicitの意味がわからないやつは単一引数コンストラクタにはすべてexplicit付ける事。
628 :
621 :2001/06/11(月) 16:54
知らなかった…… class a { public: a() {m_i=0;}; a(int i) { m_i=i; }; protected: int m_i; }; void func(class a) { } func(1);
629 :
デフォルトの名無しさん :2001/06/11(月) 20:55
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
630 :
デフォルトの名無しさん :2001/06/11(月) 20:55
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
631 :
デフォルトの名無しさん :2001/06/11(月) 20:55
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
632 :
デフォルトの名無しさん :2001/06/11(月) 20:55
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
633 :
デフォルトの名無しさん :2001/06/11(月) 20:56
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
634 :
デフォルトの名無しさん :2001/06/11(月) 20:56
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
635 :
デフォルトの名無しさん :2001/06/11(月) 20:56
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
636 :
デフォルトの名無しさん :2001/06/11(月) 20:56
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
637 :
デフォルトの名無しさん :2001/06/11(月) 20:56
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
638 :
デフォルトの名無しさん :2001/06/11(月) 20:56
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
とりあえず落ち着け
640 :
デフォルトの名無しさん :2001/06/11(月) 21:53
641 :
デフォルトの名無しさん :2001/06/11(月) 22:04
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
642 :
デフォルトの名無しさん :2001/06/11(月) 22:04
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
643 :
デフォルトの名無しさん :2001/06/11(月) 22:04
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
644 :
デフォルトの名無しさん :2001/06/11(月) 22:04
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
645 :
デフォルトの名無しさん :2001/06/11(月) 22:04
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
646 :
デフォルトの名無しさん :2001/06/11(月) 22:04
int &Fact() { int a = 10; return a; } int main() { int a = Fact(); cout << a << endl; return 0; } これはだめなんでしょうか 結果は 10 ってなったんですが
落ち着いたみたいだね。 さて、結論から言えば駄目です。 ローカル変数の参照を返すのは全て駄目です。 何でも動けばいいってもんじゃない。
648 :
デフォルトの名無しさん :2001/06/12(火) 10:44
MFCのQueryInfoStatusCodeで取得できるStatusCodeを MFC使わずに取得したいのですが、何か方法ございますでしょうか?
うんち。
>>648 (何がしたいのかイマイチよくわからんが)
ソケット開いて GET 要求出したあと、
帰ってきた 1 行目(だったかな?)に書いてある。
telnet で 80 につなげて GET 要求出してみりゃ、すぐわかる。
651 :
651 :2001/06/12(火) 15:52
thisってどうして自分のポインタを返すのですか?
thisの意味を英和辞典で調べるように。
>>651 thatだと相手のポインタかな…って思っちゃうでしょ?
655 :
651 :2001/06/12(火) 19:08
仕様なのでしようがないのですか?
>>655 そのオチが言いたいために質問したのですか?
657 :
82 :2001/06/12(火) 19:21
おい、82、 クッキー残ったままだぞ。
659 :
デフォルトの名無しさん :2001/06/12(火) 20:32
660 :
デフォルトの名無しさん :2001/06/12(火) 20:32
クッキーとビスケットとサブレとクラッカーの違いはなんですか
あたり前田のクラッカー。
ポケットビスケットつ
ポケットビスケットつ
665 :
デフォルトの名無しさん :2001/06/13(水) 02:49
VCでクラスに初チャレしたんですが、 externで他のソースの関数を使うみたいに 他のソースのクラスにあるpublic関数を使う方法って 無いんでしょーか? 厨房な質問ですんまそん
publicなら、そのクラスの定義をincludeすれば使えよう。
>>665 使用するクラスのヘッダをインクルードすればよいだろう。
メンバ函数をさもグローバル函数のごとく使おうと思っているのなら
設計レベルの話しになるが。
668 :
デフォルトの名無しさん :2001/06/13(水) 13:32
>>667 >メンバ函数をさもグローバル函数のごとく使おうと思っているのなら
できるの?
>>668 staticにする。が、いきなりやると自動的に、メンバになってる意味があるか
どうかとかの検討(葛藤)が始まって気持ち悪くなるので、設計時によく考えて
実装すべし。
>>669 代弁してくれた。
>>668 まぁ要求するものによっていろいろあると思うけど、
はじめからグローバル函数にするとか、namespaceも考慮するとか、
static函数にするとか、同じ機能をもつ函数だけど名前をかえるとかなど。
>メンバ函数をさもグローバル函数のごとく使おうと思っているのなら >設計レベルの話しになるが。 激しく同意。 綺麗に設計されていれば、C++の機能を素直に使って実装できる。 あれこれテクを駆使しなければならないときは、たいてい 設計に問題がある。 俺もC++を使い始めた頃は他のクラスの関数を流用したいと思った。 こういう制限が出てきたときは、そのクラスの使い方を間違っているか、 そのクラスの設計に問題があるかのどちらか。
672 :
ぷらぷら厨房 :2001/06/15(金) 11:55
C++Builder5で class TDataModule1 : public TDataModule { public: __declspec(dllexport)long hoge1(AnsiString, AnsiString *); BOOL hoge2( char * , double * ); }; __declspec(dllexport) long TDataModule1::hoge1(AnsiString hogeStr1,AnsiString* hogeStr2 ) { hoge2(charhoge1,doublehoge1); } BOOL TDataModule1::hoge2( char* hogechar1, double* dwhoge1 ) { return true; } とすると、『外部シンボルhoge2がプロジェクト名.objで未解決です』という リンカエラーになってしまいます。どこが悪くてエラーになるのか分からず 困っております。低レベルなミスとは思いますが、解決法あれば教えていただけないでしょうか。
>>672 まさか return true;-->return TRUE;
でOKってことはないよね。
charhoge1とdoublehoge1ってなに? TDataModule1::hoge2(char*, double*)しかないから グローバルのhoge2()を探してるんじゃないの。
676 :
デフォルトの名無しさん :2001/06/15(金) 20:31
hage
>672 __declspec(dllexport) はヘッダーにあればインプリメントの方には要らんのと違うの?(あんまし自信無し)
>>675 その通りでした(^^;
変数渡ししてる部分とかをいじったら
コンパイル通りました。型が合わなくて
見つけてなかったんですね。
>>677 そうなんですか?何かC++の参考書見てもヘッダーか実体かどっちか
書いてないので一方なのか両方なのか分かりません。
これに限らずDLLの作成及び外部(特にVBからの)呼び方について
詳しいサイトなどあれば教えて頂けないでしょうか。
しまった、さげちゃった(^^;
続けてすみません。 DLLのコンパイルをしようとすると、 『非パブリックシンボル symbol をエクスポートしようとした』 のリンカ警告が出ます。ヘルプの説明に従って、 ・_export をプロトタイプと関数定義両方に書く。 ・スペルミスのチェック ・関数名を大文字にする 全てやりましたが警告が消えません。 また、それと直接関係あるのか分かりませんが、 VBからこの関数を呼ぼうとすると『DLL〜にメソッド〜が見つかりません。』 と言うエラーになってしまいます。 警告の理由、及び外部からの呼び出し方法についてご助言頂きたく。
なんでprivateなメンバ関数をエクスポートしようとするかな。 privateの意味をしらねーんじゃねーの(ワラ ってコンパイラに言われているんだヨ。 それとクラスをエクスポートするのは、互換性の問題が多すぎるヨ 素直にCOMオブジェクトにしろヨ。
>681 あ、もちろんpublicにして(るつもりでい)ます。 COMオブジェクトですか? 調べてみます。どうもありがとう御座いました。 はぁ、ほんま厨房・・・。
680 (というかリンカ)が言ってるのはそういう意味の "private" じゃないと思う。 declspec(__dllexport) じゃないよん、って程度のことでは。 動作に支障ないと思うけど。蛇足:どんな名前で export されたかは dependancy walker で見るとすぐわかる。
684 :
デフォルトの名無しさん :2001/06/20(水) 01:25
>>681 672にpublic と書いてあるっての。なんでウソ答える?
「(ワラ」って付けるのにロクなの居ない。
>ぷらぷら厨房
多分呼び出し名があっていない。警告は多分平気。
VBからクラスオブジェクトそのものを使用するのはCOM使うが、1メソッドだけなら
extern"C"__declspec(dllexport) long hoge1Func(AnsiString hogeStr1,AnsiString* hogeStr2)
{
return TDataModule1::hoge1(hogeStr1,hogeStr2);
}
こんな風にしてhoge1Func()を呼べばいいんちゃう?
>>681 COMオブジェクトが素直だとは到底思えない。
>>685 でもまぁ、バイナリ互換性を保持するためには COM 使ったほうが良いと思う。
C++ のクラスを DLL 化すると、プライベートなメンバ変数一つ増やしただけで
バイナリ互換性が崩れるから、COM にするかスタティックリンクライブラリにし
た方が身のため。
ここでは、C++のクラスをVBから使いたいって話じゃないのか? それなら、普通、COM使うって事になるはずだが。
>>684 それだとstaticなメンバ関数しか呼べない様な気がするけれど。
わざわざクラスにせずに、普通の関数で実装しろよ‥‥
689 :
デフォルトの名無しさん :2001/06/24(日) 11:02
下がりすぎ、あげ
690 :
デフォルトの名無しさん :2001/06/24(日) 19:08
いつになったらCみたいに処理系と分けて話が出来るようになるのかな。 現状じゃまだ個別の話がメインになってしまうなぁ。
691 :
デフォルトの名無しさん :2001/06/24(日) 19:56
質問。 C++で、メソッドのポインタを取得して メソッドコールするにはどうすればいいのでしょう? // test.cpp class Foo { public: void func() {} }; int main(void) { Foo obj; void (Foo::ptr)() = obj.func; ptr(); // ←この部分で下記のエラー return 0; } test.cpp: In function `int main()': test.cpp:9: object-dependent reference `func' can only be used in a call test.cpp:9: to form a pointer to member function, say `&Foo::func' test.cpp:10: pointer to member function called, but not in class scope
692 :
691 :2001/06/24(日) 19:59
上のソース、ちょっと修正。 void (Foo::ptr)() = obj.func; ↓ void (Foo:*ptr)() = obj.func; です。
693 :
691 :2001/06/24(日) 20:02
あ、また間違えてる。アホだ俺は。 正しくは void (Foo::*ptr)() = obj.func; です。
694 :
デフォルトの名無しさん :2001/06/24(日) 20:54
>> 691 static でないとダメなはず。
>>691 どうしてもインスタンスメソッドを呼びたければ
関数クラスみたいなものを作ってやればオケー。
>>691 何でそんなことしたがるんだ???
C++なら継承使えばいいだけじゃないか・…
C++わかってる?
この話題も定期的に出るね。 クラスのメソッドを外から呼び出したい場合、メソッドを外から呼ぶ方法を 考える前にまずそのクラスの設計を見直すべき。 ・本当にそのメソッドを外から呼ぶ必要があるのか。 ・そのメソッドはクラスに含まれている必要があるのか。 設計を適当にやり過ごして、対症療法的にstaticを乱造するなんてのは もってのほか。
C++はまともなOOPLの進化から取り残されているので method delegationをスマートに実装することができず 694-697のように泥臭い解決法しかありません。 ついでに大半のC++ユーザーはその価値を理解していません。 言語が思考を制限してしまうよい例ですね(藁
>>698 ん・・・だから、どうしてもデリゲートしなきゃいけないのか設計を見直せ
ってことになると思うんだが。
エンベッドにすると設計が泥臭くなって手に負えないが、デリゲートなら
設計はスッキリする(そのかわりC++では実装が泥臭くなる)という場面
があまり想像できないんだけど。
こんなのでたけど、どうよ? class Foo { public: void func() {} }; class Bar { Foo *pobj; void (Foo::*pfunc)(); public: Bar(Foo *p) { pobj = p; } void SetPtr(void (Foo::*ptr)()) { pfunc = ptr; } void Call() { (pobj->*pfunc)(); } }; int main(void) { Foo obj; /* 1 */ void (Foo::*ptr)() = obj.func; (obj.*ptr)(); /* 2 */ Bar bar(&obj); bar.SetPtr(obj.func); bar.Call(); return 0; }
C++では、関数ポインタテーブル的なものは完全抽象関数の サブクラスでの実装を呼び出すようなインスタンスの コレクション構造にすべきじゃない? STLのmapの呼び出し方とか、細かい事忘れちった(今は専らJava プログラマなおいら)けど、だいたいこんな感じにするとか、 どうでしょ? class AbstractFunc { public: virtual void func() =0; } class Func1 :public AbstractFunc{ public: virtual void func(); }//同じように実装いっぱい作ってちょ class FuncTable{ private: static FuncTable* instance__;//singleton instance handler map<string*,AbstractFunc*> _functionmap; public: static FuncTable& getInstance();//instance getter void setFunction(string*,AbstractFunc*); AbstractFunction getFunction(string*); } //登録方法 FuncTable::getInstance().setFuntion("Func1",new Func1()); //呼び出し方法 FuncTable::getInstance().getFuntion("Func1")->func();
>>698 俺はデリゲートがスマートな実装だとは思えないな。
テンプレートを実装できない/したくない言語が、
苦肉の策で実装するもの。あまり綺麗には見えない。
実際、多重継承もテンプレートもあるC++にデリゲートは不要だとおもう。
C++の機能の範囲で必ず綺麗に実装できるよ。
>>691 これじゃあ駄目なわけ?
class IFoo{
virtual void func() = 0;
};
class Foo1 : public IFoo{
virtual void func() { cout << "foo1" << endl; }
}
class Foo2 : public IFoo{
virtual void func() { cout << "foo2" << endl; }
}
int main(void)
{
Foo1 obj1;
Foo2 obj2;
obj1.func();
obj2.func();
sub(obj1);
sub(obj2);
}
int sub(IFoo &f)
{
f.func();
}
704 :
>702 :2001/06/25(月) 00:14
>>691 の例題程度なら何でもいいけど
デリゲートするメソッドがインスタンスあたり数個〜2・30個あって
さらに実行時に飛び先が変わってくるようなケースでも
きれいに実装できる?
705 :
デフォルトの名無しさん :2001/06/25(月) 00:17
>>704 mapのキー検索条件を、そのとび先を決定する条件にすれば、
別にいくつあろうと問題ないと思うけど、そういうわけにも
いかないのでせうか?
706 :
デフォルトの名無しさん :2001/06/25(月) 00:37
707 :
>705 :2001/06/25(月) 00:56
やりたいのは単なるクラス版関数ポインタなわけで、 単にCの関数ポインタ呼び出すときに 頭にthisポインタ埋め込めればいいだけ。 これは言語レベルでサポートすべきだと思う。 # サポートされていない現状でどう実装すべきかはあんまり興味ない。 それを>701の実装みたいにメソッドオブジェクトnewして 文字列キーにしたmap持ち込むってのは大げさ過ぎると思う。 # そういやMFCのGUIオブジェクト->イベントハンドラへの # メッセージの伝播ってどうやってんの?
708 :
デフォルトの名無しさん :2001/06/25(月) 01:16
->* .* 使えって。
>>707 Windows伝来の邪法ながら、COMの秘技を用いれば、
インスタンスメソッドを、「第一引数がインスタンスポインタな関数」
に格下げすることができる、と聞きまする。
ちなみに、MFCは hWnd->CWmd変換テーブルを引いてthisを解決し、
メッセージハンドラマクロで巨大なswitchを生成して、msg -> func
をディスパッチしていたように記憶している。
710 :
デフォルトの名無しさん :2001/06/25(月) 03:52
C++で関数ポインタ使う人は、 unionとかも使ったりするんでしょうか?
たとえばwindowsとかだと APIを叩いたときに typedef union _LARGE_INTEGER { struct { DWORD LowPart; LONG HighPart; }; LONGLONG QuadPart; } LARGE_INTEGER; こんなの使うことも多々あり。 C++でOSやハードよりの泥臭いところをさわろうとすれば 必ずunionとか、必要になってくるよ。
712 :
デフォルトの名無しさん :2001/06/25(月) 04:38
>>710 あ、いや、Cレベル(あ、PASCALか?)APIしか持たないOS
にアクセスする時や、
組み込みみたいに資源の制約があるときに
関数ポインタやunionを使うのは仕方ないと思います。
でも、自分の設計するclassで
FunctionObjectやPolymorphizmが大げさすぎるという理由で、
関数ポインタやunionを使ったりする人がいるのかな〜
と思ったもので。
そういうケースも有りでしょう。 Cのようにメモり効率重視のデータ格納を行う クラスがあってもおかしくないです。
714 :
691 :2001/06/25(月) 12:42
うぉ、予想以上にレスが多くてありがたいです
>>694 staticでかつメンバにアクセスする場合は
static void func(Foo *_this) という感じの関数を作るわけですよね
エレガントにメンバにアクセスしたいのでそれは避けたいかな・・・
>>700 (obj.*ptr)() ってこんな書き方ありですか?
一応clでコンパイル&実行できました(gccだとコンパイルエラー)
715 :
691@C++わかってない :2001/06/25(月) 13:46
元々Cのソースで関数をテーブルにしてコールする処理を
C++化しようとして
>>691 の例を作ったのですが、
本来は下のようにしたかったわけです。
class Foo {
private:
void func0() {};
void func1() {};
public:
void call(int no) {
void (Foo::*table[])() = {func0, func1};
table[no]();
}
};
C++だとメソッドポインタは動的に変化する可能性があるから
静的なテーブルは作れないということですか。
でも実行時にテーブルを作っても table[no]() の部分はコンパイルが
通らないし、結局 static void func0(Foo *self) しか方法はないのかな。
あと
>>703 のvirtualにする方法はテーブルにしたい場合にどのような
メリットがあるのかちょっとわかりません。
デリゲート関係ないんじゃん(藁
>>715 だから設計を見直せ。
本当に本当にクラスのメンバである必要があるか?
staticにしてもメンバのアクセスのためにthis受け取るならグローバルだって
構わないと思わないか?
717 :
デフォルトの名無しさん :2001/06/25(月) 16:07
>>715 なんだよー、それって要するに
void call(int no){
switch(no){
case 0:func0();return;
case 1:funcl();return;
}
}
を関数ポインタでの呼び出しに無理矢理している
だけじゃないけ。そういうのは、C++では継承つか
ってswitchしないようにするって言うのがセオリー
でしょうが・・・セオリーに逆らう理由は何ナノよ?
719 :
691@C++わかってない :2001/06/25(月) 22:17
>>716 設計を見直せと言われてもなぁ(w
継承しないからクラスのメンバである必要はないし、
グローバルなthisを受け取る関数するのも構わない。
でも、それだとC++にしたメリット(thisを隠せる)がないような。
そういうものなのかな。
>>717 うーーん、そのセオリーの意味がよくわかんないわ。スマソ。
例の補足だけど実際は funcX() は全部で30個ぐらいあるんですよ。
>>719 そいつはただのブローカーだ。中間流通であくどく儲けてるだけ。
Commandパターンを使えに一票。
721 :
デフォルトの名無しさん :2001/06/25(月) 23:08
つーかC++なんだから生の関数ポインタはやめようや。 これからは関数オブジェクトです。
722 :
デフォルトの名無しさん :2001/06/26(火) 01:51
初心者です。 学校の授業で以下のプログラムを説明せよという宿題が出たのですが、 病気で休学していたので、さっぱりです。 どなたか簡単にせつめいしていただけないでしょうか。 まことにぶしつけなのは承知ですがどうかお願いします 分かっていることは、ペイントソフトのプログラムみたいです。 void_fastcall TForm1::BtnCLsClick(TObject *Sender) { Image1->Picture->Bitmap->Width=320; Image1->Picture->Bitmap->Height=240; Image1->Picture->Bitmap->Canvas->Pen->Color=clWhite; Image1->Picture->Bitmap->Canvas->Brush->Color=clWhite; Image1->Picture->Bitmap->Canvas->Rectangle(0,0,320,240); PaintBox1->Canvas->CopyRect(ClientRect,Image1->Picture->Bitmap ->Canvas,ClientRect); }
友達に聞けよ。いるだろ?
724 :
722 :2001/06/26(火) 01:54
>>723 休学していたので全然親しくないんです。
っていうか電話も知らない。提出明後日なのに。
ヒントだけね。CopyRectで検索かければわかるよ。
>>722 ていうかこのアロー演算子の羅列に誰か何か言うことはないのか?
学校でC++Builderか〜
> PaintBox1->Canvas->CopyRect(ClientRect,Image1->Picture->Bitmap->Canvas,ClientRect); PaintBox1->Canvas->CopyRect(PaintBox1->ClientRect,Image1->Picture->Bitmap->Canvas, Rect(0, 0, Image1->Picture->Bitmap->Width, Image1->Picture->Bitmap->Height); では?
Builerてこうなるんですか。 わかりやすくていいな。
732 :
デフォルトの名無しさん :2001/06/26(火) 03:34
授業でこんな基本的な事を教わるのってすっげーもったいないと思う。 せっかくだから秘伝とか教えてもらえればいいのにね。
void_fastcall TForm1::BtnCLsClick(TObject *Sender) { Image1->Picture->Bitmap->Width=320; 絵の幅は320だ。 Image1->Picture->Bitmap->Height=240; 絵の高さは240だ。 Image1->Picture->Bitmap->Canvas->Pen->Color=clWhite; 絵をいじるときに使うペンの色は白だ。 Image1->Picture->Bitmap->Canvas->Brush->Color=clWhite; 塗りつぶすときのブラシの色は白だ。 Image1->Picture->Bitmap->Canvas->Rectangle(0,0,320,240); (0,0)の点と、(320,240)の点で作成される矩形を書くぞ。 PaintBox1->Canvas->CopyRect(ClientRect,Image1->Picture->Bitmap ->Canvas,ClientRect); ペイントボックスにコピーするぞ。 }
って所だと思う。
(320,240)は含まれないってところは引っかけか?
736 :
デフォルトの名無しさん :2001/06/26(火) 06:08
>>709 メッセージハンドラマクロで巨大なswitchを生成しているのはATLで
MFCは、メンバ関数へのポインタの配列を使っている。
>>717 >を関数ポインタでの呼び出しに無理矢理しているだけじゃないけ。
あなたの主張がまさにATLのMFCに対する皮肉だ。
>>691 同じことを何度言ったか覚えているが
メンバ関数へのポインタはオブジェクトを介してのみ呼び出すことができる。
(ptr_to_obj->*ptr_to_mfct)(10);
class Foo {
private:
void func0() {};
void func1() {};
public:
void call(int no) {
void (Foo::*table[])() = {func0, func1};
(this->*table[no])();
}
};
「あるオブジェクトを介したメンバ関数へのポインタ」をオブジェクトと
して扱うことは許されていない。しかしながら、表記の通り、
「オブジェクト」と「メンバ関数へのポインタ」のペアがそれを容易に代替できる。
仮想関数に満足できない場合、一般的に使われる方法である。
実際、メンバ関数へのポインタは、仮想関数の論理的な実装の一部と言える。
737 :
デフォルトの名無しさん :2001/06/26(火) 09:36
>>717 セオリーに逆らう理由は何ナノよ?
ウィンドウズのメッセージの数だけ vitrual 関数を用意すると、
vtbl が肥大化するうえに、結局根っこの WndProc ではさらにさらに
巨大な switch 文 (map とか引いても良いけどさ) が必要になるから。
738 :
691@C++わかってない :2001/06/26(火) 09:51
>>720 意味わからんわ。
>>691 あんたスゲーよ!
>(this->*table[no])();
この方法でコンパイル&実行できたし!
これでthisを受け取る関数をボコボコ作る必要は無くなった。感謝。
あと少し補足。
メソッドポインタをテーブルに置く部分は、
func0 から &Foo::func0 に変更すると
gcc でもコンパイルが通るようになりました
739 :
691@C++わかってない :2001/06/26(火) 12:52
↑なんで自分にレスしてんだアホ。
>691じゃなくて
>>736 へのレスです
すごくまっとうな意見の
>>721 が無視されてたから書いてみました。
#include <vector>
#include <iostream>
class Foo {
struct FuncT { virtual void operator()(void) = 0; };
vector<FuncT*> table;
struct Func0 : FuncT { void operator()(void) {cout <<"itte";}; };
struct Func1 : FuncT { void operator()(void) {cout <<"yosi";}; };
public:
Foo() {
table.push_back(new Func0());
table.push_back(new Func1());
};
void dispatch(int no) {
FuncT* f = table[no];
(*f)();
};
};
main() {
Foo foo;
foo.dispatch(0);
foo.dispatch(1);
}
ファンクションオブジェクトに名前をつけなきゃいけないのが好きくない。
Javaだったらanonymousクラス使うのに
>>742 おっ、そんなのあったんか。
同じっす。考え方は。
>>701 や
>>703 と
普通の発想なのに
>>691 に無視されてるのはなぜ?
そもそも、数字をキーに関数を呼ぶってのがカタギの発想じゃないなぁ
状態マシン(しかも動的に遷移図が変わる)でもつくってるのかな?
>>743 どっか変かな。g++だと通りますよ。ただし全角空白->半角空白で。
745 :
701 :2001/06/27(水) 13:37
おいらがmapでsingletonで書いてるから、そこに目がいって無視されたらしい なあ。そこは単なる例で、枝葉の話であって、要は関数オブジェクトのコレクション にするのがC++のセオリーって事なんだけどー。 こういうやり方の時って、関数オブジェクトを作ったり消したり繰り返すような ことは普通ない(普通は初期化時にやるわな)から、STATIC関数と比較して メモリ上のコストやオブジェクト生成のCPUコストなんかそんなに意識する必要 がないと思うけど。特に今どきのマシン環境なら。 呼び出す時に、 コレクション検索→クラスメソッドコール→VPTRテーブル参照→関数実体コール という流れと、 添字番号による配列からの関数ポインタ検索→関数ポインタによる直接コール との間で段数が違う分だけ、オーバーヘッドが有るだろうけどね。 ただ、そんなもんが気になるなら、そもそもなんでC++つかってんのよ?と思う けど。CかASMででもでやればよいジャン。
>>715 で本人がいってるけど、要するに30個もクラスつくりたくね〜って
事じゃないかな。或いは、ディスパッチされたメソッドで、thisを弄りたい
とか。
個人的には、「マクロで生成された、switch使うディスパッチ関数」
って奴の出番だと思うけどな。
747 :
デフォルトの名無しさん :2001/06/27(水) 15:47
有限状態オートマトンというか状態遷移マシンを素直に実装する ときには、メンバ関数へのポインタでも十分じゃあないかなあ。 過ぎたるは及ばざるがごとし、ってことわざもあるし。 (大は小を兼ねるともいうけど)
>>747 そのようなC-styleが素直と言う人もいるとは思うけど、
わざわざメンバ関数にするメリットはないのでは?
名前空間分ける目的なら、namespaceつかえば良いし。
C-styleで何十ステートもある状態マシンやるなら、
いっそのことyaccでも使った方がお手軽だと思う。
C++でOOなら素直に一状態、一オブジェクトでしょう。
感覚的にも解りやすいし、使い回しが簡単になる。
遷移ヒストリー機能を付けたりとか、undo機能をつけるとか、
やりたくなったときにすぐに対応出来る。
なにより、遷移図がUMLで描けるのが嬉しいはずでは?
# なんか
>>691 から話が離れていってる。スマソ
749 :
デフォルトの名無しさん :2001/06/27(水) 20:55
晒し上げされちゃったよ〜
>>749 すんまそん。マジどこかわからないっす。
newしっぱなしなのは勘弁して下さい。
Java厨なもんでdelete使えないです。
BC++落としてコンパイルしたら、 table.push_back(new Func0()); でwarningがでた。(動くけど) 警告 W8030 test_fobj.cc 15: 'x' パラメータ(vector<Foo::FuncT *,allocator<Foo::F uncT *> >::push_back(Foo::FuncT * const &))のために一時変数を使用する(関数 Foo: :Foo() ) 体言止めで言われてもわからない‥ ポインタの参照にnewしたのを直接渡しちゃダメなのかな? やっぱりC++難しい。鬱だ。
>>751 原則:
参照渡しするためには、対象となるオブジェクトがアドレスを持っていなければならない。
つまり、ポインタの参照渡しには、どこかのメモリ空間上にポインタ変数が置かれていなければ
ならない。
OK?
>>752 わかりました〜。ありがとうございます〜。
754 :
691@C++わかってない :2001/06/27(水) 23:15
>>701 (
>>745 )
あー、メソッドのポインタを取得してコールするという話で、
どうしてハッシュ(というかmap)が出てくるんだよぉー
と、お察しの通りそこに目がいって早とちりしてしまいました。すんまソ。
>>741 (
>>744 )
なるほど、それが関数オブジェクトっていう事ですか。いいですねー。
それで実装する場合は、どういう感じになるか、
operator()とかは不慣れなだからfuncにして、
ほぐして、改造してみました(delete無いままだけど)
// コンパイラはg++
#include <vector>
#include <iostream>
class FuncT {
public:
virtual void func(void) = 0;
int bar; // メンバを全てのFunc?::func()で共有したかった
FuncT() {
bar = 0;
}
};
//
>>746 のいう通り↓これを30個書くのはめんどくさい
class Func0: public FuncT {
public:
void func(void);
};
class Func1: public FuncT {
public:
void func(void);
};
class Foo {
vector<FuncT*> table;
public:
Foo() {
table.push_back(new Func0());
table.push_back(new Func1());
};
void dispatch(int no) {
FuncT* f = table[no];
f->func();
};
};
// ここより上はヘッダということで
void Func0::func(void) {
cout << "Func0:" << bar << endl;
bar++;
}
void Func1::func(void) {
cout << "Func1:" << bar << endl;
bar++;
}
main() {
Foo foo;
foo.dispatch(0); //=> Func0:0
foo.dispatch(1); //=> Func1:0 ←barは共有されてない
}
755 :
691@C++わかってない :2001/06/27(水) 23:16
上の続き
一状態、一オブジェクトは拡張性があっていいとは思ったけど
そもそもfunc0とfunc1はメンバ(実体)を共有する必要があったんですよ。
上のソースだと独立したオブジェクトになってるので、
メンバが共有されないの当然ですね。
んで、今回、自分のやっているのは関数オブジェクトも魅力的だけど
>>747 のいう通り
>>736 の方法を使うのが適しているように思いました
ここ上下関係がはっきりしてて読みやすいです。 へんなアオリもないし、的確な突っ込みは入るしw みなさんありがとう
>>755 あう?
共有する実体ってのが変数の事なら、関数オブジェクトに
その変数持ってるインスタンスを引数でわたせばよいじゃん。
758 :
デフォルトの名無しさん :2001/06/27(水) 23:40
>>751 -753
何が分かったというのだろう。
newの戻り値のポインタが一時オブジェクトとして作成され、
それのconst参照がpush_backに渡される。
つまり警告は冗長であり、そのコードは完全に正しい。
>>758 一時オブジェクトなら、vectorが破棄されたときに、
その一時オブジェクトも破棄されるんじゃない?
もしこれを記述した人が、永続的に存在して
deleteされないオブジェクトを作ったつもりでコードを書いたなら、
期待通りの動作をしないよね。
だからwarningが出ないと危険だし、
errorにしてもいいくらいだと思うぞ。
>>757 それもいい方法なんだけど、void func0(Foo *_this) という風になって、
C++化したおかげで_thisを葬れるというメリットがなくなってしまうヨ。
761 :
SdC :2001/06/28(木) 00:08
【delete のエラー?】 VC++ のコンソールモードでプログラミングをしています。 クラス内において、new で動的に生成した配列を、デストラクタにおいて delete [] で解放しようとしたら、デバッグ窓に、 Heap block at 00342808 modified at 00342A80 past requested size of 270 みたいな文が表示されて停止してしまいます。(コンパイル後の実行ファイルに対するデバッグのような画面になります。) このエラーの意味自体もよくわからないのですが、どこがいけないのでしょうか?
>Heap block at 00342808 modified at 00342A80 past requested size of 270 00342808番地に確保されたヒープブロックにおいて、 確保したサイズ"270"を超えたところにある、 00342A80番地が変更されてしまっています。 const int size = 270; int *p = new int[size]; p[size+1] = 10; delete []p;
ていうかさ、エラーメッセージを読む気が無いなら、 プログラムしないで下さい。 そのほうが人に迷惑をかけずに人生をまっとうできます。
>>760 this渡しは隠蔽されているだけで、実際には行われているよ
メリットでも何でもないよ。
>>760 ポインタ一個引数に渡すのに、何かデメリットがあるの?
>>764 葬れるというのは言い方がおかしかった。隠蔽ということですね
>>765 見た目的な美しさ以外には、特にデメリットは無いだろうな。
でも確かになんか違和感がある。
だけどさ、やっぱ根本的に問題があるでしょう。
このお題そのものに。
C++の制限の多くは、機能的な不備よりも、
下手な設計を排除するためにわざと制限していることが
ほとんどだと思うのだけどどうよ。
>>759 一時的で、破棄されてしまうのは、ポインタオブジェクト(妙な言い方)
そのものであって、newで確保した「ポインタの指し示す先」ではない。
void test()
{ char *tmp = new char; }
という関数があったとして、tmpは破棄されるけど、
newで確保した領域はそのまま残るだろ。
ちなみに、
>>749 のリークってのは、Foo::~Fooで、
tableにあるFuncT解放していない、って事。
>>766 thisを不用意に晒さないですむという意味かな。
ちょこっとだけ気持ちを理解した。
でも、C++は、きれいに書くためのプログラミング言語じゃないと思う。
どうしてもというなら、
Cから引き継いだプリプロセッサ機能や
関数オブジェクトを書いて
汚いと思えるところを隠蔽すればいい。
自己満足にならない程度に、きれいに書こうね。
Func1::func(Foo* foo){ foo->setHage(foo->getBaka()+foo->getTimpo()); foo->funcHoge(foo->getTimpo()); } とかやる(汚すぎな例だね(藁))のは、Visitorパターンとか いうデザインパターンの適用例といって良いんじゃない? これって汚いロジックなのかなあ?
(゜д゜)<friend関数はだいたいきちゃない
>>758 const参照の時は、初期化するものが左辺値でないと、
一時オブジェクトが作成されるんですね。
んで、一時オブジェクトは参照がつくられたスコープの間
存在するので、それがリークする事はないと
>>752 は、一般的な(constでない)参照の初期化の時に
は正しいと
C++こわいよ〜
>>758 オブジェクトは生成されるけど、ポインタ自身はアドレス空間上に置かれてないってことだろ。
コンパイラが親切に一時オブジェクトを作ってくれてるだけだ。
>>762 ありがとうございました。解放する配列とは別の配列のインデックスが上限を越えていました。
これからはきちんと英文エラーメッセージも反芻して精進します、ご迷惑をおかけいたしました。
>>773 ここで作られた一時オブジェクトは、つまり、ポインタのことだ。
一時的に作られたポインタは、参照渡しが終わって関数から戻ってくるとメモリ上から消える。
newで確保したオブジェクトは、deleteで明示的に消さない限り残るので
この場合リークするよ。
しっかり勉強しろ
777 :
デフォルトの名無しさん :2001/06/28(木) 01:35
>>759 悲劇的だ。的はずれで何を言ってよいか私には分からず、
彼は自分があらゆる質問に答える権利を有していないことを宣言したに等しい。
一時オブジェクトの分からない貴方はあと20分ほど本を読む必要がある。
このキャラに限界を感じている私は、貴方に本気でへこまないでほしい
と言うことしかできない。
778 :
デフォルトの名無しさん :2001/06/28(木) 01:41
>>774 ポインタの一時オブジェクトが作成され静かにアドレス空間に置かれる。
>コンパイラが親切に一時オブジェクトを作ってくれてるだけだ。
もう私は書くペンを持っていない。
このコンパイラがたまたま親切にも一時オブジェクトを作ってくれている
とでも言いたいのだろうか。
>>776 deleteしないとリークするのはわかってるよん。
実害無いから放っておいただけ
前半は理解しました。ありがとうございます。
781 :
>>769 :2001/06/28(木) 03:01
この場合メンバ関数へのポインタを使うのが綺麗だと思うのだが。 T* _this を渡して、操作はもろもろ protected なり public なり にする、なんてのはどー考えても変だぞ... (たとえば PPP なんかを実装する場合を考えてみてくれ)
これってやっちゃダメ? delete this; 当然だけどデストラクタをprivateなんかに放り込んで newでしかclass生成できないようにしてだけど。 あと、newの配列を使えないようにしとかないとダメか。
>>782 使いかたを間違えなければ可
COMのQueryInterface::Releaseの実装でも使われとります。
delete後にクラスのメンバをいぢったりしてはいけない。
784 :
デフォルトの名無しさん :2001/06/28(木) 20:37
C++でのnamespaceの扱い方の定石をご教授願います。 例えばstlを使おうとした場合に 入門書なんかだと 例1: #include <memory> using namespace std: int main(int argc, char* argv[]) { auto_ptr<Hoge> AutoHoge(new Hoge); } 見たいな感じになっていますが・・・ 自分はつい最近までstlの専門書(つーかC++の専門書)をあまり読んだことがなかったのです。 今までは我流でこんな感じにやっていました。 例2: #include <memory> int main(int argc, char* argv[]) { std::auto_ptr<Hoge> AutoHoge(new Hoge); } namespaceをせっかく使ってるんだからこのやり方のほうが 名前空間を汚さなくていいんじゃないかと思っているんですが・・・ せめて 例3: #include <memory> int main(int argc, char* argv[]) { using std::auto_ptr; auto_ptr<Hoge> AutoHoge(new Hoge); } の方がいいと思うんですが・・・ よかったらそれぞれのメリット・デメリットを踏まえて定石をご教授ねがいます。
785 :
デフォルトの名無しさん :2001/06/28(木) 23:17
age
>>784 あなたの主張はもっともだと思います。
必ずしも書籍が正しいとは限りません。
タイプ量が増えるのがイヤな人と、
名前空間以前のコンパイラをサポートするためのものだと考えるのが
妥当だと思います< using namespace
書籍はコードを簡略化するためにやってるだけだろ。
789 :
:2001/06/29(金) 16:02
using namespace デフォルトの名無しさん;
790 :
すみません。。 :2001/06/29(金) 16:19
スミマセン、これってなんで bbb と表示されるんでしょうか...? bool flag; flag=true; if(flag==true) cout << aaa << endl; else cout << bbb << endl; まったく謎なんです、、。どなたかわかりましたら教えて下さい(;´Д`)
791 :
790 :2001/06/29(金) 16:21
しかもデバッガでflagの値を見ると '・' なんです、、。
792 :
名無しさん :2001/06/29(金) 16:54
>>790 gccだと稀にメソッド内でメンバー変数にちゃんと代入できない
バグのあるバージョンがあるみたいだけど。
egcs-2.9xという表示の出る奴。
変数をpublicにして外から代入すると直る。
793 :
790 :2001/06/29(金) 17:00
>>792 さん
public で直りました!
本当にありがとうございます!
794 :
名無しさん :2001/06/29(金) 17:03
>>793 こういう対処は悲しいね。
良いバージョンが出回ることを望みます。
>>783 ありがとうございます。
のど元に引っかかってた骨が取れました。
796 :
「partial」の意味について :2001/06/30(土) 00:35
1.Class template partial specializations クラステンプレート部分特別バージョン 2.Partial ordering of class template specializations クラステンプレート特別バージョンの部分順位付け 3.Partial ordering of function templates 関数テンプレートの部分順位付け 1.の「部分」は、「部分的に」テンプレート引数が 特定されているということですが、 2.と3.の「部分」は、数学用語らしい「部分順位」 のことだと考えています。 だから、2.をより詳しく書けば、 Partial ordering of class template partial specializations クラステンプレート部分特別バージョンの部分順位付け と書けると思います。 これは正しいでしょうか?
797 :
shige :2001/06/30(土) 01:42
ハハハ ∧_∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ( ^∀^)< あほか ( つ ⊂ ) \_________ .) ) ) (__)_) (^∀^)ゲラゲラ ruby >>>>>>>>>>>>>>>>>>>>>>> C++
798 :
デフォルトの名無しさん :2001/06/30(土) 08:03
ruby しかできない人なのか...
800 :
デフォルトの名無しさん :2001/06/30(土) 19:16
printfで%pでのアドレス表示は、coutではどうやったらいいんですか。
int *p; cout << p
%p表示と同じ書式で出したいというならしらーん あれはコンパイラの作りに依存するからね
803 :
デフォルトの名無しさん :2001/06/30(土) 19:49
>>800 int *p;
cout << (int)p
ってのはだめか?
>>803 16bitの頃のx86でHugeModelだったとして、それ書いて逝ってよし
sprintf最強ってことでいいですか
806 :
デフォルトの名無しさん :2001/07/01(日) 03:33
_snprintfの方がもっとずっと、いろんな意味でよいのだが 標準でないので逝ってくる。 ベンダの提供するcoutの出力で我慢できない?
807 :
とうちゃん :2001/07/02(月) 00:30
クラスの相互参照ってどうすればよし? たとえば class A{ B b; .... } class B{ A a; .... } ってエラーがでるんですが、、、
808 :
デフォルトの名無しさん :2001/07/02(月) 00:33
>>807 class B;
class A{
B b;
....
}
class B{
A a;
....
}
ってやってみ?
809 :
デフォルトの名無しさん :2001/07/02(月) 00:34
class B; class A{B b;}; class B{A a;}; 内部メソッドを呼びだすインライン関数はclass定義中には書けないよね?>ALL
>>809 その内部メソッドが既に定義されてればできる.
>>810 言葉足りずスマヌ、もちろん相互参照等で定義されていない場合。
812 :
デフォルトの名無しさん :2001/07/02(月) 00:53
はーい質問。 C++でインスタンス化されていないクラスのメソッドを呼びだす方法について質問です。 どこぞで3つある、と聞いたのですが、 1:static void fuction(..) 全然問題ないですね。 2:reinterpret_cast<A*>((void*)0).function(); 大抵のコンパイラなら問題なさそうですね〜。 もちろんfunctionの中でメンバ変数にアクセスしてたら死亡です。 3:??? 俺にはこの程度しか思いつかなかったんですが、他にありますか?
>>812 そういう状況に陥ったことないのだが、
なんでそんなことするんだ?
>>813 意味はありません。ただ3つもあるのか?と思っただけで。
もちろんstaticにするのが当たり前です
>>814 俺が無知なへぼプログラマかと思っちゃったよ。
ただのへぼでよかったんだ。
わーい
>>815 俺はへぼでいいから答え教えろやゴルァ
817 :
とうちゃん :2001/07/02(月) 01:07
>>808 その方法でやってみたんですが
うまくいかなくて、、、
#include <stdio.h>
class B;
class A{
private:
int value;
B *b;
public:
A(void);
int get(void);
int get_b(void);
};
A::A(void)
{
value = 0;
}
int A::get(void)
{
return(value);
}
int A::get_b(void)
{
return(b->get());
}
class B{
private:
int value;
A *a;
public:
B(void);
int get(void);
int get_a(void);
};
B::B(void)
{
value = 100;
}
int B::get(void)
{
return(value);
}
int B::get_a(void)
{
return(a->get());
}
なかんじです
Aの関数定義をBの宣言の後に持っていくべし
820 :
デフォルトの名無しさん :2001/07/02(月) 01:12
>>817 定義されて無い関数は呼べません。
定義されていないクラスは使えません。
821 :
Java使いなのでC++ようわからん :2001/07/02(月) 01:12
これはできないのかな? static void Hoge::hage(){} Hoge* hoge = NULL; hoge->hage(); どうせHoge::hage()で呼べるんだから、 全く意味がないと思われるが…どうでしょうか。
出来るけど、それが解答だとするとちょっと残念だな。 とにかくtnx>821
823 :
デフォルトの名無しさん :2001/07/02(月) 01:15
>>821 借りの実体を与えてやれば呼べるって奴でしょ。
それ2番と同じだよ。
そして、これも又同じ。
A &a = *(A*)NULL;
a.function();
824 :
Java使いなのでC++ようわからん :2001/07/02(月) 01:21
じゃあ、関数ポインタ直呼び?これはできるの? (*func)() = Hoge::hage(); func(); みたいな?これはC++じゃないと思われるが。
825 :
とうちゃん :2001/07/02(月) 01:23
>>820 てことは
>>821 -823
みたいにやらないと相互参照はできないってことですか?
(といっても なにしてるかよくわkらん、、、
勉強しなおそう!)
826 :
デフォルトの名無しさん :2001/07/02(月) 01:25
>>825 ちがうちがう、あれはまた別の話(^^;
#include <stdio.h>
class B;
class A{
private:
int value;
B *b;
public:
A(void);
int get(void);
int get_b(void);
};
class B{
private:
int value;
A *a;
public:
B(void);
int get(void);
int get_a(void);
};
A::A(void)
{
value = 0;
}
int A::get(void)
{
return(value);
}
int A::get_b(void)
{
return(b->get());
}
B::B(void)
{
value = 100;
}
int B::get(void)
{
return(value);
}
int B::get_a(void)
{
return(a->get());
}
>>825 自分の人の良さにあきれるが…答えてやろう。
本来この程度のことは試行錯誤して解答を探し出すもんだが。
class B;
class A{B b;public:B* get_b();};
class B{A a;public:A* get_a();};
void A::get_b(){return &b;}
void B::get_a(){return &a;}
これを参考にしてみそ
828 :
とうちゃん :2001/07/02(月) 01:33
>>826 クラスの定義を先にもってくればいいんですか。
ありがとうございます。
でもクラス定義を別々のヘッダーでする場合はどうすれば?
、、、とこれはもっともっと勉強してから
いつかしたいと重います
>>827 (中途半端に勉強した)CからC++へ移って
こまりはてています。がんばって勉強しますかな
どうもです。
829 :
デフォルトの名無しさん :2001/07/02(月) 01:44
//file1 class B; class A{B b;public:B* get_b();}; // file2 class A; class B{A a;public:A* get_a();}; //file3-4 void A::get_b(){return &b;} void B::get_a(){return &a;} だろ
//Sample.h #if !defined(Sample_H__uuid__INCLUDED_) #define Sample_H__uuid__INCLUDED_ class A; class B; class A { /* メンバ変数定義、 メンバ函数宣言 */ }; class B { /* メンバ変数定義、 メンバ函数宣言 */ }; #endif //Sample.cpp #include "Sample.h" /* メンバ函数定義(実装) static メンバ変数初期化 */ //Reference.cpp #include "Sample.h" //class A,B を使って実装
831 :
機知guy :2001/07/02(月) 15:37
age
832 :
とうちゃん :2001/07/02(月) 20:56
せっかくおしえていただいたのに・・・ できねっす・・・
試行錯誤ねえ エバると有難がられる、か...
C++BuilderでPaintのプログラムを打ってるんですが、 Imageコンポーネントって具体的に言って、どういう働きをして どういうことができるんですか? あと、ビットマップとはなんですか?
835 :
00 :2001/07/03(火) 12:14
kokoyori yasasii sure ha naissuka?
837 :
デフォルトの名無しさん :2001/07/04(水) 03:53
どうしてもあるデータに対して、それを管理するクラスと参照するだけの クラスに分けたものを作りたく思い次のようにやってみました。 class A{ Data data; public: const Data* getData(){ return &data; } }; class B{ const Data* pRefData; public: B( const Data* d ) : pRefData( d ){} }; main(){ A a; B b( a.getData() ); } friendにするまでもない、ということで上記のようにしてみましたが やはりあまり誉められたやり方ではありません。 このことをもう少し綺麗に行う方法ってないでしょうか?
>>837 やりたきゃやってもいいけど設計間違え気味。
見るだけクラスを元クラスから派生、もしくはその逆にしなさい
>>837 "UML" "関連クラス" で検索してみな?
>>838 両クラスの役割が違うこともあって考えもしませんでした。確かにそうですねぇ。
>>839 dataを分離して関連クラスにしてしまうわけですか。こっちもいいなぁ。
どちらでいくか迷いますが、悩みが高尚なものになって嬉しいです。
お二人ともありがとうございました。
GoF読み始めたらクラス設計つまんなくなって来ちゃったよ。 俺の車輪は世界一ィィィ
842 :
デフォルトの名無しさん :2001/07/06(金) 03:37
age
843 :
デフォルトの名無しさん :2001/07/06(金) 12:05
なぜ thread関数は、staticメンバにしないとだめなんでしょうか?
844 :
デフォルトの名無しさん :2001/07/06(金) 12:52
>>843 thread 関数に this を渡せないから。(Microsoft Visual C++ の実装の場合)
845 :
843 :2001/07/06(金) 13:41
>>844 さんの
ヒントでthisを渡せない理由を調べてみました。
どうやら関数呼び出し規約に秘密が隠されていそうです。
__stdcall、__cdeclの違いがビンゴのようです。
thiscallは__cdeclと同じ仕様でスタックにthisが積まれ、
非staticメンバ関数の呼び出し規約であるということなので、
__stdcallで呼び出されるthread関数はstaticにしなければならない
ということなのですね。
846 :
名無しサン :2001/07/06(金) 13:49
つーかソレ以前に最適化の結果渡らなくなったり バージョンアップで実装が変化したりするするから Cの関数にthis渡すなってこともある。 どうしてもメッセージパッシングしたければCOMだけど C++とCにはオーバースペックだなぁ。
847 :
844 :2001/07/06(金) 13:53
>>845 いや、違うよ。
__thiscall は __stdcall とよく似てるが、
ecx で this が渡される点が違うのよ。
すなわち、VC++ の実装では this はスタックには積まれない。
仮に引数のないメンバ関数(実質 __cdecl と同じ)があったとしても、
やっぱり this を渡せないことには変わりがないので、
thread 関数は非スタティックなメンバ関数を呼び出せない。
848 :
843 :2001/07/06(金) 18:33
>>847 度々ありがとうございます。
呼び出し規約を誤って理解するところでした。
何故スレッドが__stdcallでなければならないのか?
という疑問も有りましたが、スタックのクリアを自分自身で
行うということなので、スレッドの終了時に都合がよさそうだ
と納得しました。
849 :
デフォルトの名無しさん :2001/07/06(金) 21:11
>>848 OS の API が C++ を前提にしてないから、だよ。
例えば EPOC などの C++ に特化した OS だと、Thread も
C++ のオブジェクトを使ってナニソレする。
850 :
3B :2001/07/06(金) 21:14
851 :
ど素人 :2001/07/07(土) 23:00
C++のStringクラスの実装ってどうなってるんでしょうか?
ソース読め>851
853 :
デフォルトの名無しさん :2001/07/07(土) 23:27
言語実装や最適化以前の問題として、
OSが要求するのは割り込み「関数」だから、だろう。
割り込み「メソッド」じゃないので、
(やりかたの如何を問わず)thisポインタをやり取り
する手段(Interface)が用意されてないというだけのこと。
>>849 ん?興味あり。EPOCとやらではどういう感じになってるんですか?
VCやDelやJavaみたいに内部実装のthreadに一対一対応
するThreadクラスがあって、そいつのインスタンスのrunメソッド
とかがOSによって動かされる、みたいなスタイルっすか?
まとめ:
非Object用であるthreadをObject用に翻訳する機能を
MFCなりVCLなりJVM(?)なりが持っている、ってわけだなー。
854 :
デフォルトの名無しさん :2001/07/08(日) 01:04
C++前提のOSってBeOSがたしかそうだと聞いたことがある。 いつだかの互換性のないバージョンアップのときに 大変なことになったらしい。 需要がなけりゃ問題にもならんけどね。
855 :
デフォルトの名無しさん :2001/07/08(日) 03:11
去年の今ごろBoland C++compilerなんかを何も分からずにインストールして 放置していた者です。 それから1年が起ちましたがCドライブが圧迫されてきてファイルを削除しなければ ならない状況に追いこまれ、ファイルのデカイC++を消そうと思った次第です。 が、アンインストールの方法がかいていないのでとても困っております。 どなたか教え手下さい。
素直にディレクトリごと消せば良し
857 :
デフォルトの名無しさん :2001/07/08(日) 03:46
>>852 あんなデッカイプログラムをディレクトリごと消去ですか?
レジストリに膨大なファイルが残る気がするのですが。
信じていいのですか?
レジストリにファイルが残るという表現が謎…
859 :
デフォルトの名無しさん :2001/07/08(日) 08:06
>>857 レジストリのどこを使っているのですか?
C++ビルダーが大量に使っているのは知っているのですが・・
BCCが、どこを使っているのか、わかりません・・
860 :
デフォルトの名無しさん :2001/07/08(日) 08:08
>>857 レジストリは、あなたの気分で残るわけでもなければ、
もとファイルがでかいかどうかで残るわけでもないです。
「書け」と命じられたから書かれる(そして残る)んです。
それだけのことでしょ?
恥ずかしながら ソースの見方がわかりません...
862 :
843 :2001/07/08(日) 12:14
849,853,854 OSとAPIの都合が真相のようですね。 この2、3日勉強して理解が更に深まった感じです。 今思うとVC++スレに質問する内容であった気がします。 レスありがとうございました。
アンインストーラーがレジストリをきれいにしてくれるなんて ただの妄想。
864 :
デフォルトの名無しさん :2001/07/08(日) 15:01
c++では printfツカワナイホウガイイノデスカ・・・?
Windowsならファイルの検索でクラス名を指定して探しなさい。 ソースファイルをインストールしてないだけなら、 CDかWEBから探してきてインストールしなさい。 ソースを公開していないようなコンパイラを使用しているなら あきらめなさい。
いまいちcoutが使いにくいのは気のせいですか。
俺もそう思う
869 :
sage :2001/07/09(月) 00:51
・・・さげまちがえた・・・
871 :
美加 :2001/07/09(月) 22:45
c++を始めたばかりなんですが、 単語を覚えるのに void→ボイド int→イント include→インクルード という風に、頭ではカタカナにして覚えると覚えやすんですけど、 cin とか、読めないものがあるんですよね。(シーアイエヌと覚えている) どこか、カタカナ表記されているホームページとかってありませんか?
872 :
実験君 :2001/07/09(月) 22:54
class AAA { public: AAA(int i); operator int(); private: AAA(const AAA&); }; AAA getAAA(); int main(int argc, char* argv[]) { AAA a(getAAA()); return 0; } これコンパイル通ります?
getAAA()って何処の星にあるのよ。
875 :
872 :2001/07/09(月) 23:31
aの初期設定の時に、getAAAの戻り値に対して ユーザ定義変換operator int()が使用されるのか知りたい。 VC++では通らないのだが おそらくC++標準では通るのではないかと。 ちなみに A a((int)getAAA()); ならもちろん通る。
で、それ使って何やるの? 使わないほうがいいような・・・
877 :
872 :2001/07/09(月) 23:39
auto_ptrの実装を見てこの問題に直面した。 話せば長い。
試してないけど operator int () cosnt にしたらどうなる?
879 :
872 :2001/07/09(月) 23:57
>>878 うちでは特に変わらずやはり通らないなあ
調べずに書いてすまぬ。 privateなAAA(const AAA&)がじゃまをするね。 #include <stdio.h> class AAA { public: AAA(int i) {} operator int() { } private: // AAA(const AAA&); }; AAA getAAA() { AAA aaa(1); return aaa; } int main(int argc, char* argv[]) { AAA a(getAAA()); return 0; } ここまでしかできんかったよ。
881 :
デフォルトの名無しさん :2001/07/10(火) 00:10
>>880 そういうことだと、それはデフォルトのコピー
コンストラクタ呼んでるだけになるんじゃない
のでしょうか?
operator int()が暗黙的に呼ばれて AAA(int i)が次に呼ばれるんだと思う。 ところで、privateのコンストラクタを消すのは反則なの?
883 :
872 :2001/07/10(火) 00:16
>>880 -881
そう。デフォルトコピーコンストラクタの使用は禁止して
operator int()とAAA(int i)を使わせたい。
これがC++標準で可なのか知りたい。
不可なわけはないと思うのだがARM12.3.1に微妙な記述がある。
884 :
872 :2001/07/10(火) 00:19
>>882 消したらoperator int()は呼ばれない。
その通りだ。 退却する。
886 :
872 :2001/07/10(火) 10:11
アクセス権の違いによって多重定義が解決されることはない のでコンパイラは正しかった。 というわけで以下がまさに知りたいことだったのですが class AAA { public: AAA(AAA&) { } // const をなくす AAA(int i) { } operator int() { } }; AAA getAAA() { return AAA(1); } int main(int argc, char* argv[]) { AAA a(getAAA()); return 0; } getAAA();の返す一時オブジェクトに対してAAA(AAA&);(constでない)は呼べないので operator int()が呼ばれるはずだが、VC++では呼ばれません。 (というより一時オブジェクトはさっくり削除されてAAA(int i)だけが呼ばれる。) 他のコンパイラではどうでしょうか。
これじゃ駄目なの? AAA a(static_cast<int>(getAAA()));
あ、getAAAはインライン関数じゃないものとして。
889 :
デフォルトの名無しさん :2001/07/11(水) 01:01
VC++とBC++5.5ではどっちのほうがANSIに近いのでしょうか?
Originatorをいろいろ派生させました。で、 内容をMementoに保存したいんですが、この場合 Mementoに渡すStateも派生させちゃったりして いいものなんでしょうか。礼儀的に。
892 :
デフォルトの名無しさん :2001/07/13(金) 22:07
g++でのコンパイル時に、汎用クラスのコンストラクタに関して"undifined reference" って言われました。クラスの宣言部のみをヘッダファイルにして、実現部は別ファイルにあります。 これらを一つのファイルで実現するとうまくいきました。なんで? templateではないクラス の場合はファイルを分割してもうまくいくのに。
>>892 普通のクラスはコンパイル時に機械語を生成することを期待される.
template はインスタンス化しないと機械語を生成しないから、と予想.
894 :
デフォルトの名無しさん :2001/07/14(土) 01:24
>>892 宣言間違ってるとかでは?
コピーペーストしてみ
895 :
892 :2001/07/14(土) 01:32
>>893 >
宣言部と実現部を別ファイルにした場合にうまくいかないというのはなぜですか?
分離させることで何が起こるんでしょう?
コンパイラに実現部のありかを知らせる方法でもあるんですか?
896 :
デフォルトの名無しさん :2001/07/14(土) 02:23
あたま大じょぶ?>895 ふつーインライン展開と同じ理屈が適用されると思うんだけど。
897 :
892 :2001/07/14(土) 02:33
>>892 普通のクラスは分離させてもOKで、テンプレートクラスはそのままではだめというのが、
>>893 の話だと思うし、その意味もなんとなくわかります。
がしかし、どうすればテンプレートクラスでも分割できるのかがわかりません。
すんません初心者なもので。
898 :
デフォルトの名無しさん :2001/07/14(土) 02:35
#includeで依存関係ちゃんとやってる?>897
899 :
892 :2001/07/14(土) 02:51
>>898 定義のみを記述したヘッダファイルを、実現部のあるファイルとクラスを利用する
メインのファイルとにincludeしています。2重に読みこまれないように、#ifndef
も使っています。
テンプレート(の実装の多く)はマクロと同じで、 実際使う時にソースコード本体が必要になる。 ので、分割コンパイルはできない。 どうしてもファイルをわけたかったら、 *.inl のようなファイルにわけて、 それを *.h のケツで #inlcude するとか、 コンパイル速度の向上には有効でない方法を取るのが良いかと。 保守性はまあ、あがるかも知れないし、あがらないかもしれない。
インクリメンタルコンパイルをオプション指定すれば、 多少は向上しなかったっけ?>速度
悲惨な902のいるスレ
904 :
デフォルトの名無しさん :2001/07/14(土) 16:25
関数と変数が入ってるクラスをwriteメソッドで保存したら、メンバ関数はどうやって保存されるのですか?
>>904 ふつうはインスタンスの持つデータしか保存しないので
メソッド自身は保存しません。
906 :
デフォルトの名無しさん :2001/07/14(土) 16:45
なるほど。それは良いことを聞きました。どうもありがとうございました。
907 :
デフォルトの名無しさん :2001/07/15(日) 13:09
>>904 シリアライズに関わる問題は気ぃ付けろよ。
908 :
デフォルトの名無しさん :2001/07/15(日) 14:48
v(^・^)v
909 :
906 :2001/07/15(日) 21:32
>907 シリアライズって、どんなことですか? あと、スタテクライブラリを作ったあと、他のプロジェクトで使うときに、リンクにライブラリを加えた後ヘッダファイルをインクルードさせているのですが、もっと楽な方法ありませんか?
>>909 シリアライズとは、オブジェクトの状態を保存しておくこと。
あとでロードしたり、通信で送ったりして、
オブジェクトの状態を復帰させるのが目的。
ライブラリ化でそれ以上楽な方法は無い。
強いて言えばライブラリ化せず、常にソースごとコピー。
911 :
906 :2001/07/16(月) 19:28
わかりました。どうも有り難うございました。
912 :
v :2001/07/20(金) 00:16
すみません、DLL内でクラス内部に class DllExport me{ vector<int> a; } と宣言すると、'a' : class 'std::vector<int,class std::allocator<int> >' は __export キーワードを使って class 'me' にエクスポートしてください。 という警告文が出るのですが、何故ですか?
>>56 いろいろなコンパイラが吐き出すコードを見てきたけど、
仮想関数テーブルの持ち方について見た限りでは
どのコンパイラも同じような実装だった。
とにかくコンパイラが出力した結果を見てみると勉強になる。
解ってしまえば単純な実装ばかりだけれど、
不安がなくなるというのは大きい。
C++ほど実装が丸見えなOO言語は珍しい。
アセンブラの知識があればほとんど把握できるぞ。
スレ間違いです。 すまん。
915 :
デフォルトの名無しさん :2001/08/01(水) 00:53
age
てすと
end
919 :
デフォルトの名無しさん :01/09/14 00:52
a
∧ ∧ / ・ / ';, / '; / '; / ;______/ ; / \ / / \ \ /´ ( ) |____| ( ) | | ///// ( | :| ) ///// | | ( ) :| | ( ( | | ) ( | | ) ) | | ( ) '; / ( ( / \ ) ( \/ ) ) ../ ヽ ........:::::::<