C++相談室 part26

このエントリーをはてなブックマークに追加
1v(^・^)v
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
また、テンプレートライブラリ(STL含む)に関する質問は
専用の別スレへどうぞ。

過去スレ、関連スレ、関連リンクなどはこちら>>2-7
2v(^・^)v:03/11/30 12:54
■過去スレ■
 1 http://mimizun.mine.nu:81/2chlog/tech/piza.2ch.net/tech/kako/980/980175292.html
 2 http://pc.2ch.net/tech/kako/996/996640937.html
 3 http://pc.2ch.net/tech/kako/1003/10038/1003832761.html
 4 http://pc.2ch.net/tech/kako/1009/10090/1009071535.html
 5 http://pc.2ch.net/tech/kako/1014/10142/1014217496.html
 6 http://pc.2ch.net/tech/kako/1018/10184/1018454705.html
 7 http://pc.2ch.net/tech/kako/1021/10217/1021787032.html
 8 http://pc3.2ch.net/tech/kako/1025/10250/1025010364.html
 9 http://pc3.2ch.net/tech/kako/1027/10273/1027347982.html
 10 http://pc3.2ch.net/tech/kako/1029/10293/1029315669.html
 11 http://pc3.2ch.net/tech/kako/1032/10323/1032345774.html
 12 http://pc3.2ch.net/tech/kako/1035/10350/1035005882.html
 13 http://pc3.2ch.net/tech/kako/1038/10380/1038031395.html
 14 http://pc2.2ch.net/tech/kako/1041/10413/1041328679.html
 15 http://pc2.2ch.net/tech/kako/1043/10436/1043605481.html
 16 http://pc2.2ch.net/tech/kako/1045/10457/1045746245.html
 17 http://pc2.2ch.net/tech/kako/1047/10475/1047560042.html
 18 http://pc2.2ch.net/tech/kako/1050/10501/1050177746.html
 19 http://pc2.2ch.net/tech/kako/1052/10526/1052625846.html
 20 http://pc2.2ch.net/tech/kako/1055/10551/1055162298.html
 21 http://pc2.2ch.net/tech/kako/1057/10575/1057580107.html
 22 http://pc2.2ch.net/tech/kako/1060/10603/1060361082.html
 23 http://pc2.2ch.net/test/read.cgi/tech/1062690663/
 24 http://pc2.2ch.net/test/read.cgi/tech/1066546387/
 25 http://pc2.2ch.net/test/read.cgi/tech/1067949669/
3v(^・^)v:03/11/30 12:55
■基本■
[C++ FAQ]
 http://www.parashift.com/c++-faq-lite/
 http://www.bohyoh.com/CandCPP/FAQ/ (日本語)
  Cとその仕様を比較しながらの解説なので分かりやすい。
  ***** 質問の前に必ずこの二つに目を通してください *****

[禿 Stroustrup]
 http://www.research.att.com/~bs/
[C++ International Standard]
 http://www.kuzbass.ru/docs/isocpp/
 http://www.kuzbass.ru/docs/ansi_iso_iec_14882_1998.pdf
 http://www.iso.org/iso/en/CatalogueDetailPage.CatalogueDetail?CSNUMBER=38110&ICS1=35&ICS2=60&ICS3=
[JTC1/SC22/WG21 - C++]
 http://std.dkuug.dk/jtc1/sc22/wg21/

[C/C++ Users Journal]
 http://www.cuj.com/
[cppll (ML)]
 http://www.trickpalace.net/cppll/ (日本語)
4v(^・^)v:03/11/30 12:56
5v(^・^)v:03/11/30 12:56
6v(^・^)v:03/11/30 12:57
■関連スレ■
[C++】template 統合スレ]
 http://pc2.2ch.net/test/read.cgi/tech/1066493064/l50
[C/C++の宿題をやって。おながい。]
 http://pc2.2ch.net/test/read.cgi/tech/1067175933/l50
[初心者にVisual C++を教えるスレ]
 http://pc2.2ch.net/test/read.cgi/tech/1056280510/l50
[VisualC++(MFC限定)相談室]
 http://pc2.2ch.net/test/read.cgi/tech/1056584836/l50
[ATL 相談室]
 http://pc2.2ch.net/test/read.cgi/tech/1029029882/l50
[C/C++でのWindowsPrograming議論スレ(質問お断り)]
 http://pc2.2ch.net/test/read.cgi/tech/1049790146/l50
[COMの世界を斬る!]
 http://pc2.2ch.net/test/read.cgi/tech/981823340/l50
[managed C++ やろうぜ!!]
 http://pc2.2ch.net/test/read.cgi/tech/1014486422/l50
[C++Builder相談室]
 http://pc2.2ch.net/test/read.cgi/tech/1061594556/l50
[タダで使えるBorland C++]
 http://pc2.2ch.net/test/read.cgi/tech/1054390397/l50
[Borland C++ BuilderX]
 http://pc2.2ch.net/test/read.cgi/tech/1065260556/l50
[Code of the Nerds" Digital Mars C/C++]
 http://pc2.2ch.net/test/read.cgi/tech/1044210976/l50
[GCCについて]
 http://pc2.2ch.net/test/read.cgi/tech/1046179115/l50
[OpenWatcom C++]
 http://pc2.2ch.net/test/read.cgi/tech/1033433728/l50
[タダで最強!フリーC/C++コンパイラ]
 http://pc2.2ch.net/test/read.cgi/tech/1035882599/l50
ラッキー7
末広がりの八
>>1
  _、_
( ,_ノ` )y━・~~~ グッジョブ!
10デフォルトの名無しさん:03/11/30 13:22
配列オブジェクトの動的確保を、引数つきのコンストラクタで
初期化しながらやりたいんですけど、どうしたらいいでしょうか?
例えば
double *a = new double[p](int x, inty)
とかだとダメのようなのですが、どう書けばできますでしょうか?
>>10
無理
std::vectorなら条件付で可能だが。
「STLでコードサイズが10倍」云々のコピペは
今回は無しか
returnで値を返すところで、エラーがでてしまうのだけど、
どうして?
getline()ってグローバル関数版もあるの?
仕様もistreamクラスのメンバ関数とかなり違うみたいですが
できればリターン値とか引数の仕様とか教えてくらはい
一応具具ったんですがわからなったので
istream& getline(istream&,string&,char);
もっとぐぐれ
さすが2chッ!俺が分からないことを即レスで返してくれるッ!
そこにシビれるッ!憧れるぅぅぅッ!
こんなエラーが出てプログラムが強制終了されてしまうのですが、
何が原因なのでしょうか?
ある関数を出たときにこうなってしまうのですが・・・。

'ntdll.dll' をロードしました、合致するシンボル情報は見つかりませんでした。
'C:\WINDOWS\system32\kernel32.dll' をロードしました、合致するシンボル情報は見つかりませんでした。
'C:\WINDOWS\system32\user32.dll' をロードしました、合致するシンボル情報は見つかりませんでした。
'C:\WINDOWS\system32\gdi32.dll' をロードしました、合致するシンボル情報は見つかりませんでした。
\system32\shell32.dll' をロードしました、合致するシンボル情報は見つかりませんでした。
'C:\WINDOWS\system32\SHLWAPI.DLL' をロードしました、合致するシンボル情報は見つかりませんでした。
'C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.10.0_x-ww_f7fb5805\comctl32.dll' をロードしました、合致するシンボル情報は見つかりませんでした。
'C:\WINDOWS\ime\IMJP8_1\DICTS\imjpcd.dic' をロードしました、合致するシンボル情報は見つかりませんでした。
'C:\WINDOWS\system32\oleaut32.dll' をロードしました、合致するシンボル情報は見つかりませんでした。
スレッド 0xC64 終了、終了コード 3 (0x3)。
20r:03/11/30 14:55
class Base {
};

class Ext : public Base {
};

なとき、

void Copy( Base* targ, Base* src ) {
*targ = *src;
}

とかやると、
Ext e1, e2;
Copy( &e1, &e2 );
の呼び出しでBaseのoperator=が呼ばれてしまって、
期待通りのコピーができなかったりします。

みんなはどうやって解決してる?r
21デフォルトの名無しさん:03/11/30 15:16
>>20
void Copy( Ext* targ, Ext* src ) {
*targ = *src;
}
>>20
おまいさんがやりたいのは本当にコピーなのか?
Copy() に Base* で渡している時点でオブジェクトの実際の型は不明になっている。
*targ, *src のそれぞれが Base あるいは Ext の可能性があるが、この 4 通りでどういう処理が発生すれば
期待通りなんだ?

で、オブジェクトの複製が欲しいだけなら、Base に
virtual Base* clone(void);
を定義すればいいと思う。
template<class T>
void Copy( Base* targ, Base* src ) {
  static_cast<T>(*targ) = static_cast<T>(*src);
}

Copy<Ext>( &e1, &e2 );
STLつかうと一気に実行ファイルサイズが10倍に?!
はぁ、またか。
処理にかかる時間も10倍になります
はい、次
>>24
ダイナミックリンクも白根ーのか知障
>>28
煽られると放っておけない人情味のある方ですね
ソースの読みづらさも10倍になります
>>24
環境によるだろ。
俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力
ランタイムを使用するようにして使っているが、例えばstd::vectorを
使っても使わない時と比べ10Kほどしか増えない。
>>31
すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。
3313:03/11/30 19:16
俺が呼んだのか? この場合・・・。
とりあえず?!じゃなくて!?じゃないのとかね…
>>32
きっとインポートテーブルのサイズなんか考えたこともないし
もしかして存在すら知らないんだろうな (プププ
>>33
粘着召喚士ですか?
ねぇねぇ。みんなコピペってコレクションしてるの?
それとも毎回探してくるの?
>>37
新スレが立つと「コピペ辞書」から適当なモノを自動で書き込む
スクリプトを走らせてますが、何か?
2
STLつかうと一気に能率が10倍に?!
STLつかうと一気に辛さが10倍に?!
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。
とかいうエラーが出るんだけどこれってどうすればいいの?
.pch ファイル削除してリコンパイル
(☉◇☉)
(☉◇☉)
やっぱり、C++でprintfやsprintfを使うのは邪道なんですかね?
でも、coutを使うのはしんどいんだよな…
>>46 さぁ?
>>46
なれればcoutも捨てたもんじゃないぞ
>>42
#include <stdafx.h>

後死ね。
>>49
言葉が悪いな。それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。
51デフォルトの名無しさん:03/12/01 07:58
>>46
boost::format
質問です。
Foo( 型 )
{
CBase* myc = dynamic_cast <CBase*> (new 型);



}
こういう感じで型を引数にする方法を調べてます。

template<typename T> Foo (T in)
{
CBase* myc = dynamic_cast <CBase*> (new T);



}
こんな感じでできそうですが、これだと引数に渡すためにTのインスタンスを
作成しないといけなさそうなんで、もっとスマートな方法があったら教えてください。
何をしたいのか解らない。
とにかくC"Base"にdynamic_castって何?

template<typename T> Foo (T *in)
インスタンス無しで呼びたいなら、
template<typename T> Foo();
こうだろ。
55 ◆niIReSAISE :03/12/01 08:56
int a ;
5653:03/12/01 09:07
確かにテンプレート引数を省略しなければいいのか。
無理矢理コンパイラに選択させようとしていた。
foo(static_cast<Class *>(0));
5752:03/12/01 09:09
53,54さんありがとうございました。解決しました
多相型オブジェでCBaseは変だよ
>CBase* myc = dynamic_cast <CBase*> (new T);
TがCBaseと継承関係に無い場合リークするぞ。
それとも例え?
その前にエラー
61デフォルトの名無しさん:03/12/01 11:32
Variant型の変数の作り方を教えて。
62デフォルトの名無しさん:03/12/01 11:57
マクロって何すか???
>>61
Variant 変数名;

こんな基本的なことも知らんでどうする。

>>62
C入門書嫁。
>>63
Variant型の定義の仕方を教えてください。
65デフォルトの名無しさん:03/12/01 16:34
class Cls2;

class Cls1 {
public:
friend void Cls2::func();
}
----------------------------------
class Cls2 {
public:
void func(){return;};
}

というように、friendを使いたいのですが、
compileするとCls2::func()が定義されてないよーと怒られます。
ただし、-----------のところで、二つのfileの分割しています。

どのように書けば良いのでしょうか。
66デフォルトの名無しさん:03/12/01 16:35
>>65
------------------より下をインクルードすればいいんじゃないか?
6765:03/12/01 16:52
書き忘れましたが、
下のfileでは上のfileを既にincludeしています。
そりゃだめだろうね。
friend void Cls2::func();からfriend class Cls2;だといいんだが
下のファイルで上のファイルを
インクルードしないで済むようにするとか。
70デフォルトの名無しさん:03/12/01 20:49
C++でJavaのinterfaceみたいなことやるには純粋仮想関数じゃなくて仮想関数にしなきゃだめなんですか?
むしろC++,Java,抽象クラス,インターフェースについてまとめてください、おねがい
>>70
いや不純仮想関数は禁じられたゼットォォォだぞ
72デフォルトの名無しさん:03/12/01 22:07
g++3.3を使っています。
class hogehoge があったとして std::vector<hogehoge> を

for(std::vector<hogehoge>::iterator it=v.begin();
it!=v.end();it++){

hogehoge* h=it;

}

のように代入するとしかられます。どのようにすべきなんでしょうか?
>>72
hogehoge* h = &*it;
>>72
なぜイテレーターをわざわざポインターにするの?
>>74
そりゃ当然便利なイテレータの性質をはぎ取って不便なポインタにしたい
からでしょう。>>72はマゾ。
7672:03/12/02 16:39
>>75
マゾではないなあ。
hogehoge* を引数とする関数があるからだけど、他に良い方法があるのでしょうか?
ない
72はマゾではないかもしれないが、ここの住人はあえて教えないサドばかりだ。
>>76
で、イテレータも必要なのか?
本当はイテレータなんていらないんだけど、参考書丸写しで>>72のfor文使ってるだけってことない?
vectorはCライクな配列としてアクセスできるって知ってるよね?
以上を踏まえて、それでもってのなら>>73は定石だから覚えておいて損はないよ。
80デフォルトの名無しさん:03/12/02 20:05
vectorの各要素に対する処理をforで記述するときは
何も考えず>>72のように書くのもひとつの方法ではないだろうか。
目覚めてないというか自覚のないマゾの見つけ方
軽〜く髪を引っ張ってみる
明確な判定基準はないがそれなりの反応を確認できる
82デフォルトの名無しさん:03/12/02 20:36
public class Sub extends Super implements InterFace

をC++で記述するとどうなりますか? Mixinとの多重継承になりますか?

83デフォルトの名無しさん:03/12/02 20:39
C++で文字列解析するのって、みなさんどうしてますか?
print "Hello,World!"
を「print」「"」「Hello,World」「"」に分解したいんですが。
84デフォルトの名無しさん:03/12/02 20:43
boost::lex
85デフォルトの名無しさん:03/12/02 21:22
質問いいですか?
int *i;
delete [] i;
みたいにまだnewで領域が割り当てられていないときにdeleteしたら
どうなりますか?
メモリが割り当てられているかどうか判別するにはどうしたらよいですか?
>>85
> みたいにまだnewで領域が割り当てられていないときにdeleteしたら
> どうなりますか?
大抵の環境で落ちると思う。

> メモリが割り当てられているかどうか判別するにはどうしたらよいですか?
とりあえず、割り当て前は NULL で初期化しておく。
8785:03/12/02 21:31
>>86
レスありがとうございます。
int *i;
i=NULL;
ですか?あとでif(i)で確認すればよいのですね。
int *i;を宣言したとき、iは最初からNULLではないのですか?
>>87
ISO の規格を見てちと補足。
new で確保したアドレス以外を渡すと delete および delete[] の動作は未定義。
なので何が起こるかわからない。まぁ大抵の場合は落ちると思う。
で、NULL を渡した場合は何も起こらないと規格で決まっているので if で判別する必要はない。
関数内とか auto として定義した場合は、int *i としたときの i の値は不定。
明示的に初期化すべき。;
89デフォルトの名無しさん:03/12/02 21:38
>>88
> NULL を渡した場合は何も起こらないと規格で決まっている

free()と同じだな
9087:03/12/02 21:43
どもありがとうございます。
とりあえず明示的にNULLで初期化しておけば良いのですね。
なんか電波を受信してint *i;を宣言した当初はNULLだと勘違いしてました。
>>87
関係ないが、宣言と初期化は1文にしましょう
int *i = 0;
9287:03/12/02 22:17
>>91
はい。
classのメンバ変数にint *i;を入れたときとかは
コンストラクタでi=NULL;でいいですか?
>>92
class hoge {
int *i;
public:
hoge() : i(NULL) {};
};
9487:03/12/02 22:55
>>93
あ、そのやりかた知りません。
メンバイニシャライザでi(NULL)って書き方できるんですか?
9582:03/12/02 23:13
70ではありません(70が言ってることは、ちょっと理解できないところも
あります)。

でも、javaとC++の対応表みたいなものがあると助かるのは70と同意見です。
漏れは C++ からJavaをやりだしたんだけど
細かいところがいろいろ違って面倒。
>>94
ほぼなんでもあり。関数呼び出しだってできちゃうよ。
>>97
ん?
class A{
int value;
A(int value):????(value){}
};

????の部分はなんて書けばいいのでしょうか?
>>99
A(int value) : value(value) {}
でメンバ変数を引数で初期化、になるので安心せよ。
>>100
そうだったんですか。
なんかダメっぽい気がしてthis->value(value)としたら通らなくて困ってました。
サンクスです。
つーか引数名変えればいいじゃん。
A(int val) : value(val) {}
>>102
おまえは中学生か?
バルバルうるさいなぁ
>82
class Sub : public InterFace , private Super
バルバルバルバルゥゥゥゥゥッ!
俺用メモ

>>100 は ISO 規格 12.6.2-7 に例つきで載っている。
引数じゃなくてメンバを参照したい場合は、this->value。
ただし初期化順序に注意する必要あり。
>>103
なんで中学生がどうとかいうツッコミをいれてるのかさっぱりわからん。
>>99のケースでどう書けばいいかわからないなら引数名を変えろってのは、
至極もっともなアドバイスだと思うんだが。
同一変数名の識別方法みたいな微妙なルールがわからないとき、
必ず全部理解しておかないとまずいって考え方してるの?
初期化子では(コンパイラが仕様に準拠さえしていれば)
何も付けなくても的確に区別されるが、
それ以外ではそうはならないので、
名前を変えるのが面倒が無くて良い。
メンバに m_ の接頭辞か _ の接尾辞を付けるのがよく使われる。
だからSTL使うと
11182:03/12/03 20:26
>>105
ありがとうございます。
javaとC++の微妙な違いで少し混乱中です。
112デフォルトの名無しさん:03/12/03 21:40
配列宣言して初期化していない状態では
配列の中身はNULLと考えてよろしい?
前々から気になってたんだが、禿げローストラップ先生の本には
「delete 0 は安全だよ!」
と書いてあるよな。

一方、FDISを見ると
「delete null-pointer は安全だよ!」
と書いてあって、更に、

> 3.2.2.3 - Macro NULL [diff.null]
> -1- The macro NULL, defined in any of <clocale>, <cstddef>,
> <cstdio>, <cstdlib>, <cstring>, <ctime>, or <cwchar>,
> is an implementation-defined C++ null pointer constant
> in this International Standard (lib.support.types).
(NULLは"null pointer"を表す処理系依存の定数である)

という記述もある。
そうすると、FDIS の方に書いてあるのは
「delete NULL は安全だが、delete 0 は必ずしも安全とは言い切れない」
とも解釈できるんだが、ここんところの真意はどうなっているんだろうか?

どうせ俺の短い人生の中で NULL != 0 な処理系に出会う可能性は
ほぼ皆無なんだが、こんな根本的な仕様を知らないまま育ってきて
しまったことに不安を感じるので、できれば教えてもらえないだろうか。
NULL == 0 はANSIで決まってた予感。
115デフォルトの名無しさん:03/12/03 21:54
てことは
for(i = NULL; i < n; i++){
で問題ないと
struct afo { int dqn; };
int afo::*p = 0;
int afo::*q = &afo::dqn;
if(p == q) std::cout << "sine";
else std::cout << "gaikichi";
0はぬるぽですよ。C FAQ参照のこと。
逆にNULLのほうが規格で決まっているわけではないので、処理系依存。
(まあ0以外にdefineしてる処理系はないだろうけど)
NULLはどんな処理系でも0。
ポインタに0を代入したとき、その処理系のヌルポインタ値に変換するのはコンパイラの責任
って聞いたことある。

例えば、1がヌルポインタの処理系があった場合
そのコンパイラは
int* p = 0;
としたら1を代入しなければならないらしい。
119デフォルトの名無しさん:03/12/03 22:40
ファイル(out1.txt)のデータが
0 1 2 3 3 3 4 5 6 7 8 8 8 8 8 8 8 9 9 10...
と0から10000まで並んでいるところから、0の個数、1の個数...100の個数...
を別なファイル(out2.txt)に出力するプログラムを作成しています。
C++で作成していますので、C++で動作するプログラムをお願いします。
皆さんよろしく。
>>119
宿題スレでレスしてもらってるくせに
マルチしてるヤツって何なんだ?
偽物の可能性もある。黙ってスルーするのが吉。
>>117
スレ違い氏ね
123119:03/12/03 22:53
提出までに時間がないのですいません。
急いでいます。
>>123
真の教えて君にはまだまだ遠い。
>>113
5.2.10-5 注 64)
Converting an integral constant expression (5.19) with value zero always yields a null pointer (4.10),
but converting other expressions that happen to have value zero need not yield a null pointer.

0になる整定数式を変換すると常に null pointer になる。
しかし、たまたま 0 になるその他の式を変換しても null pointer になるとは限らない。
126119:03/12/03 23:21
まじで頼む。
>>126
他の擦れでレスついとるやンか。
マルチポストしてレスも確認せんのか。まじで死ねヴォケ
#define NULL (void *)0
って見たことある。
C++じゃなくてCだろうけど。
129デフォルトの名無しさん:03/12/03 23:49
良く C では良質なソースコードを読んで勉強するといった事を
アドバイスされますが、C++の場合も良質なソースコードを読む
事が上達の近道となりますか?その場合、具体的な良質ソース
コードの例って何かありますか?
130デフォルトの名無しさん:03/12/03 23:52
Qt
boost
132デフォルトの名無しさん:03/12/03 23:55
int* p = NULL  としたとき

 int* p = (void*)0;

となるがC++では型チェックアウトとなるので

#define NULL 0 に定義されている。
>>129
そんなもん、どんな言語でも一緒に決まってるだろ。
あと、自分のコードを人に見てもらうのもいいぞ。
人に見られることを意識するだけでもだいぶいいコード書くようになる。
>>132 logic_error
>>132
本当は

class Null
{
public:
 template<class type>
 operator type*() const { return 0; }
};
const Null NULL;

とした方がいいんだけどな。
more effective C++ 参照。
次期C++には、予約語 nullptr を入れるとかいう話があるらしいね。
できればもう改訂しないで欲しい。
ばんばん改訂して欲しい。
boostは全部STLに入れる方向で。
PortableなsocketライブラリもSTLに入れて欲しいね。
ネットワーク当たり前の時代なんだから。
漏れのはこうなって居る。

#ifndef NULL
# if defined(__cplusplus) || defined(_Windows)
# define NULL 0
# else
# define NULL ((void *)0)
# endif
#endif
C++になって、CよりNULLを使う頻度が減った。
そう思いません?
>>130
>>131
>>133
レスどうもです。

C++の場合はクラスの設計でほぼそれ以降の実装
のうまい、下手もほぼ決まってしまうような所があるので、
ちょっとCとは毛色が違うのかなという思いから質問して
みましたがやはり優良ソースを読むのが良いんですね。
俺のNULL

#define NULL (3*4-12)
ちょっと話がふくらむとすぐこれだ
俺のNULL

#define  NULL (!1)
俺のANULL

#define ANULL *
>>140
Null Object Pattern があるのだ!
他スレで放置されたのでこちらで質問させて下さい。

gdbで、実行ファイル中のオブジェクトについて調べるにはどうしたらよいのでしょう?
例えばstringな変数strの、
1) 中身の文字列そのもの
2) str.length()
について見たいのです。1)はprintで一応見れますが、他もズラズラ
見えるのでスマートでない気がします。
2)はわからないです。call も print も、 There is no member やら Couldn't find method
なんですが、これはそういうものなのでしょうか?それとも私がgdbの使い方を理解してないから?

先生方、よろしくお願い致します

gdb のバージョンが古いんじゃないか?
1) p str.c_str()
2) p str.length()
でちゃんと見える。gdb 5.2 使用
149デフォルトの名無しさん:03/12/04 08:18
>147
貴様にお父さんなどと呼ばれる覚えはない!
娘はやらん!帰れ!
>>81
抜けますた(・∀・)
私はどっちなんでしょうか
マゾだな。
>>150
ハゲるな。
そしてビヤーネへ・・・
154147:03/12/04 22:50
>>148
先生原因がわかりました。
「c++なら -gstabs オプションが -g の代わりだ」
とかぬかした先輩が原因でした。

-g オプションでちゃんと見られるようになりました。
どうもありがとうございました!
C++言語の予約語はいくつありますか?
>>155
30個ぐらい
>>155
void int signed unsigned long short float double char wchar_t bool
auto register extern static const volatile typedef
static_cast reinterpret_cast const_cast dynamic_cast
new delete sizeof typeid
enum union struct class inline template typename namespace using
public protected private friend virtual this
if else for while do switch break continue return goto
try catch throw

54個思いつたけど、他に何かあったっけ?
and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq
とか。
つか、C++3rdに一覧なかったか?
>>157のに加えて↓で全部。PLC++3rdで確認した。
and and_eq asm bitand bitor case compl default explicit export
false mutable not not_eq operator or or_eq true xor xor_eq
mutable asm explicit export true false operator case default
が抜けてるな
>>158
うわ。それ知らなんだ。

それ以外には
mutable explicit asm export true false
があったな。
というわけで、71個か。
あ、operator, case, default もあったか。
つーことは74個か。
いいケコーンっぷりだw
>>157
wchar_tは違うと思う。
stdef.hかどっかにtypedefされてると思う。
wchar_t は C では typedef だが C++ では予約語。
まーじーでー
まじまじ
予約語を全部?使ってプログラムを(いろはにほへとみたいに綺麗に意味があるような感じで)
書いてたサイトがあったな。もっといかしたのキボンヌみたいなこと書いてあったよううなきがした。
でも、export 使ったら
コンパイルできるコンパイラが限られるなぁ。
Comeau C++ くらいか?
C++ BuilderのPreview版はつかえるらしい。
171デフォルトの名無しさん:03/12/06 00:53
CとObjective-Cの知識は一通りあるので
なんとか勘でC++を使ってきましたが、
限界を感じずにはおれないので一から勉強しなおそうと思います

良書がありましたらご紹介ください
よろしくおねがいします
>>171
スレ違い。
書籍スレに逝け
>>171
このスレの1桁台のレスにいくつか挙がってるyo
174ひーん:03/12/06 13:56
何がおかしいか分からないよ
#include<iostream.h>
#include<limits.h>
wa(int);

void main()
{
int su;
cout<<"数値を入力してください"<<endl;
cin>>su;
while(!cin){//10
cout<<"不正な数値(文字)が入力されました"<<endl
<<"数値を入力してください"<<endl;
cin.clear();
cin.ignore(INT_MAX,'\n');
cin>>su;
}
cout<<"1〜"<<su<<"までの和を算出します"<<endl;
cout<<wa(su)<<"になりました";
}//20

int wa(SU)
{
int i,goukei=0;
for(i=1;i>=SU;i++){
goukei+=i;
}
return SU;
}//30
ネタかもしれんが、一応反応しといてやる。

× wa(int);
○ int wa(int su);

× int wa(su)
○ int wa(int su)

× for(i=1;i>=su;i++){
○ for(i=1;i<=su;i++){

× return SU;
○ return goukei;
>>174
> 何がおかしいか分からないよ
頭がおかしい。

>>175
> 一応反応しといてやる。
心がやさしい。
175は優しくて女にモテそうだな
178aaaaa:03/12/06 15:21
そんなものの言い方するやつが女にもてるか!
優しいだけじゃもてねぇよ
179デフォルトの名無しさん:03/12/06 15:32
先生!質問!!
getoptを使いたいのです。
C++用のクラスライブラリって調べるといくつかあるんですが、
どれが1番ポピュラーなんでしょうか?
昔のlibg++にはあったようですが、今はなくなったみたいです。
皆さんは何を使っていますか?
環境はLinux(RedHat9)です。
>175は利用される性分。

>>179
私ゃ自前で作ったのかXのToolKit任せかどっちか。
181激しい初心者:03/12/06 17:21
今日初めてクラスを勉強しました
で、本の通り行ったのですがエラーが出ます
助けてください

#include<iostream.h>
#include<string.h>

class Customer{
public:
int id;
char name[20];
};

int main()
{
Customer c;
c.id=100;
strcpy(c.name,"田中");
cout<<c.id<<endl
<<c.name<<endl;
return 0;
}

実行結果
リンク中...
LIBCD.lib(wincrt0.obj) : error LNK2001: 外部シンボル "_WinMain@16" は未解決です
Debug/クラス2.exe : fatal error LNK1120: 外部参照 1 が未解決です。
link.exe の実行エラー
182激しい初心者:03/12/06 17:32
分かりました
すんません
VisualC++でクラスウィンドウからView、そしてOnDrawを開いてそこに描画コードを
打ち込んで使っていたのです。
CPad for Borlandでコンパイルやろうとした場合(一続きのプログラム)はどうしたらよいのでしょうか?


void CkaachanView::OnDraw(CDC* pDC)
{
>>183
スレちがい 「別れようってことなの?」
スレ違いだったようで申し訳ありませんでした。
ただ、描画コードとか使ってグラフ描くときにヘッダとかどう書いたら言いのカナァと。

すいませんでした
186デフォルトの名無しさん:03/12/06 22:25
質問です。
char* str;
str=new char[100];
などとして動的にメモリを確保したとき、これを解放するには
delete str;
delete[] str;
のどちらを使えばいいんでしょうか。
delete str;
!
189デフォルトの名無しさん:03/12/06 22:35
delete str;
delete[] str;
は何が違うんでしょうか。またどのように使い分ければいいんですか?
>186
delete[] str;
>189
たいして違わない。

デストラクタの定義されたオブジェクトをdeleteするときに
一個だけデストラクタが呼ばれるか、全部のデストラクタが呼ばれるかの違い。
strがchar一個を指しているのか配列を指しているのかコンパイラには区別がつかないから教えてやらねばならんという話。
192187:03/12/06 23:12
char配列だから、即答してしまったが、訂正 delete[] str;  の方が安全だな。
>>187 (>>190も?)
なにか勘違いしてないか?
xxx = new XXX [N]; で生成したら delete [] xxx;で破棄。
xxx = new XXX; で生成したら delete xxx;で破棄。
それ以外の動作は未定義。
charやintであってもだ。
>>193
特定の処理系の話と、規格上の話を混同しているんだろうね。VC あたりだと
190 の言うとおりなんだが。

ついでに delete, delete[] で悩むぐらいなら boost::scoped_array, boost::shared_array
あるいは std::vector を使った方が良いと思うぞ。
195187:03/12/06 23:48
ちなみにMSのC++だと (今のVC++も)
delete str;に比べdelete[] str;の方が余分に関数が1つ入る。
今時1関数など無視して良いが、昔は・・・・・気にしてた時期あり。
今なら193に賛同する。
new[] は確保した数とかを保存する領域を
一緒に確保することがあるので
delete[] を使うべし。
まぁ、デストラクタが無い場合は省略されることが多いけど。
>>196
俺も同じ事を考えた。つまり new[] ではなく new で確保された領域を
delete[] で開放すると、「確保した数が保存されているはずの領域」
をアクセスするので、もしその位置が new が返す先頭アドレスとは
違っていた場合、コア吐く可能性がある。もしそうでなくても、数は
意味を持たないので、必要ない領域まで開放してしまい、ヒープ構造
は破壊されそうだ。
PageUp、PageDownキーが押下された場合のイベントを拾いたいのですが、
MSDNにそれらしいVKxxのdefineがありません。
どうやって拾うのでしょうか?
>>198
スレ違い。
保守上げ
上がってなかった
いまどき素のnewは使わないでしょ。
>>203
なにいってるの使いますよ
あなたはSTLで我慢できるお人なのですね
それともメモリープールのoperator new派なのか?
ここ最近、スマートポインタのコンストラクタ引数以外でnew書いた記憶ないな。
STATEパターン(?)っぽいことで相談です。

class Base {};
class A : public Base {};
class B : public Base {};
class C : public Base {};
class D : public Base {};

Base* Hoge(int type,int arg1,int arg2){
  switch (type){
  case 0: return new A(arg1,arg2);
  case 1: return new B(arg1,arg2);
  case 2: return new C(arg1,arg2);
  case 3: return new D(arg1,arg2);
  default: return NULL;
  }
}

こんな感じのコードがあるわけですが、
newするクラスだけが違ってほかはいっしょなので、
なんかテーブルで一括してできそうな気がするんです。
switchを使いたくねー、っていう、ただそれだけではありますけど。
207206:03/12/08 15:25
って、書いてて思い出しタ━━━━(゚∀゚)━━━━!!
Modern C++ Designのどっかに、こんな感じのことに関する記述が
なんかあったのを思い出したのでそれを読みますね。
聞いてくれてありがとうアロエリーナ。
書くと思い出しちゃうんだよね。
>>206
デザパタもC++も知らない漏れには state じゃなくて factory の
中途半端なのに見える。。。
>>209
stateで合ってると思うよ。中途半端だけど
>>203
漏れが使ってるそこそこ著名なライブラリなんぞ
newをガンガン使わせる仕様だぜ
deleteしないのがいささかキモイが
テーブル化すると、
class Base {};
class A : public Base { public: A(int a, int b); };
class B : public Base { public: B(int a, int b); };
class C : public Base { public: C(int a, int b); };
class D : public Base { public: D(int a, int b); };

template <class T> Base* CreateBase(int arg1, int arg2) { return new T(arg1, arg2); };
Base* (*fac[4])(int,int) = {
CreateBase<A>, CreateBase<B>, CreateBase<C>, CreateBase<D>
};
って感じ?
別に switch でもあまり変わらん気もするなぁ。
どうせコピペで拡張できるんだし。
あぁ、追加じゃなくて挿入したいときは
テーブルの方が便利やね。
どう見てもStateパターンじゃねーよ。Factoryだ。
State を Factory してるとか...。
>>216
でしょうね。>>212 みたいな単純な switch の置き換えの配列じゃなくて、
生成関数を map でひくとかすると面白いかも。
>>211
ObjectARX か何かですか?
すんまそん

VC6++のIDE周りの問題なんですが、質問はここでいいんでしょうか?
どこで質問すればいいのやら・・・VC++すれはMFC限定とか書いてあるし・・・
>>219
↓このへんかなぁ。
【初心者歓迎】C/C++室 Ver.3【環境依存OK】
http://pc2.2ch.net/test/read.cgi/tech/1069719929/
例えばtemplate<typename T> class NODEなら
クラステンプレートのコンストラクタには
NODE<T>() {・・・}のように
型指定の<>を付けた方が良いんですか?
いいえ
template<typename T> class Node { Node(); };
template<typename T> Node<T>::Node() { ... }
224デフォルトの名無しさん:03/12/10 15:11
質問です。

std::locale loc( "japanese" );
std::locale::global( loc );
std::ctype< wchar_t > const & ct = std::use_facet< std::ctype< wchar_t > >( loc );

std::string str1("hello world.");
std::string str2("はろーわーるど。");
char const * b1 = str1.c_str();
char const * e1 = b1 + str1.size();
char const * b2 = str2.c_str();
char const * e2 = b2 + str2.size();
wchar_t dest1[ 256 ] = { 0 };
wchar_t dest2[ 256 ] = { 0 };

ct.widden( b1, e1, &dest1[0] );
ct.widden( b2, e2, &dest2[0] );

std::wcout << &dest1[0] << std::endl; // <- (1)
std::wcout << &dest2[0] << std::endl; // <- (2)

上記コードで、(1) の行は正しく "hello world." と表示されたのですが、
(2) の部分は文字化けしてしまいました。環境は Win2k, VC++7.1 です。
(2) の部分でも正しく「はろーわーるど。」と表示させるにはどうしたらいいでしょう?
あと、他のコンパイラではどういった動作を起こすのでしょうか?
codecvtあたりについてgoogle様に伺ってみるとよろしい。
226デフォルトの名無しさん:03/12/10 15:40
質問お願いします。
Windowsで言うダイアログボックスにあたるクラスと、
とある処理を担う別のクラスMがあります。

ダイアログボックスのボタンなどが押された場合に、Mを使って処理をし、
またMの処理の結果を、ダイアログボックスに表示したく思っています。

この場合、依存関係を最小にするには、どう関連付けるのが良いのでしょうか。
相互に相手を知ってしまうと、なんだかクラスわけの意味が無い気がして…。
さりとて一緒にしてしまっては、使いまわしが利かなそううで困っています。
>>226
コントロールクラスからダイアログボックスとMに関連を張る。
コントロールクラスがないなら、ダイアログボックスとMとどちらか主体になる
クラスから他方に向けて関連を張る。
たとえば、ダイアログを主体にするなら、Mの処理を関数にして結果は戻り値で受けるようにする。


どうでもいいが、あなたが質問者なんだから、「回答お願いします」だろ。
228224:03/12/10 16:07
>>225
ありがとう。少し勉強してみる。
>>227
いや「この子をお願いします」みたいな感じの用法だし、間違ってないんじゃね
230226:03/12/10 16:36
>>227
コントロールクラスを挟むのは、いかにもスマートでかっこいいですねぇ。

しかし…、"ボタンが押された"などの通知はダイアログボックスクラスに
行くのですが、このためにどうしても綺麗に挟む方法が考えられなくて…。
結局は、ダイアログボックもコントロールクラスを知っているような
実装しか思いつきません。通知先を変えるのも複雑になるしどうすれば…。

今回はコントロールが無い場合の方で、示唆して下さった方法を使わせて頂きます。
レスありがとうございました。(質問〜は>>229さんみたいな意味で使ってました)
>>226
もう寝ちゃってるかもしれませんが、例えばA というボタンを持つ
Dialog クラス(を定義するヘッダ)は、同時にそのダイアログを利用するためのインタフェイス

class IHogeDlgListener {
public:
 virtual void button_A_pressed() = 0;
};

を提供し、使う側では

class App : public IHogeDlgListener {
 void doHogeDialog() {
  Hoge dlg(this);
 }
 virtual void button_A_pressed() {
  // dlg で A が押されたときの処理
 }
};

みたいに書くのは、割りと一般的だと思います。
232226:03/12/11 01:04
>>231
なるほど!インターフェイスだけ決めておいて
なおかつ関連づけたりせずに、引数で渡せば良いのですね。

どうも設計だの関連だのと勉強しているうちに、視野が狭くなっていました。
扱うのがモーダルダイアログな事もあって、これで益々分かりやすくなりました。
レスありがとうございました。
>>232
なんか勘違いしているような・・・
234デフォルトの名無しさん:03/12/11 16:04

基本的な質問ですいませんが、
bool flag = true;
で宣言&初期化した flag をトグルするベストな
方法ってなんでしょう?

つまり true を faulse に、 faulse のときは true にしたいのですが。

flag = !flag;
を考えてみましたが、もっとシンプルなやり方は
なかったかなと思いまして、質問しました。
>>234
false ですたね・・・
>>234
flag = !flag; を良く使う。
>>234
flag ^= false;
>flag = !flag;
それがベストだと思うけどなぁ。これ以上シンプルなのはないっしょ?

ついでだから俺も質問してみたい。
いろんなクラスに、スイッチ系のフラグがあるよね。

void On(void){flag = true;}
void Off(void){flag = false;}
bool IsOn(void)const{return flag;}

俺は大体こんな感じで制御してるけど、たまにトグルさせたいときがある。
そのときは

if (hoge.IsOn()){ hoge.Off(); }
else { hoge.On(); }

ってやるんだけど、操作はすべてひとつのオブジェクトに対するものだから

void Toggle(void){flag = !flag;}

ってのを作るべきなんかねぇ?
Effective C++ に書いてある「完全かつ最小限なインターフェース」ってのを
目指すなら、これって不要な気もする。やっぱいるか? いらんか。

あと、On(),Off()って二つ作るんじゃなくて、

SetOnOff(bool b){flag = b;}

がいいのかなー、と悩んだりもする。
どうすればいいんだ。みんなはどうしてる? 教えて。
>>237
あってるの?
>>239
無茶苦茶。
int flag = 0 or 1; として
flag ^= 1; ならいいが。
>void Toggle(void){flag = !flag;}
bool返したほうがより使える
>>236
>>238
これでよかったですか。
どもども。
>>238
フラグの意味に依る。
もしスレ違いだったら誘導ください

C++のソースコードを読むためのツールでお薦めありませんか?
例えば C で言えば emacs + global とか。
クラスが追跡しやすいといいのですが
みなさんはどのようにして読んでますか?
together最強!
値段は最凶!
貧乏人なんでフリーの奴がいいんですが。
doxygen使ってます。もちろんフリー
include <typeinfo.h>
// 使用したC++キーワードの総数 : 62
// なお、実行しても何も起こりませんのであしからず。

namespace N{
extern double D = 7.0;
template <typename T>
class C{
public:
static long L;

explicit C(T volatile * const P)
:M(const_cast<T*>(P)){
}

virtual ~C(){
try{
(*this) >> ' ';
}catch(...){
auto float f=3.14;
}
}
friend void operator >>(C& O,T P){
throw 0;
}
protected:
union{
T *M;
signed G;
};
private:
};
typedef C<char> A;

struct S : A{
enum E{
J,K,L
} Q;
mutable bool B;
S(A& O);
};
inline S::S(A& O):A(O){
if( dynamic_cast<S*>(&O) ){
register S *R = static_cast<S*>(&O);
B = reinterpret_cast<unsigned>(R) ? true : false;
}else{
for(short I=0; M[I]; I++ ){

switch((wchar_t)M[I]){
case L' ':
continue;
default:
do goto L;
while(sizeof(typeid(A)));
L:
break;
}
}
}
}
}
using N::A;
int main()
{
asm ;
delete new N::S((A&)A("Hello world"));
return 0;
}
class Base {};

class Inheritance1 : public Base {};
class Inheritance2 : public Base {};

int main(int argc, char **argv)
{
Base *instance;
switch(argv[1]){
case 1:
Base = new Inheritance1;
break;
case 2:
Base = new Inheritance2;
break;
}
}
って言うのを巧く書く方法無いですか?
継承クラスが増えてからcase書き加えていくのだるいんですけど。

int main(int argc, char **argv)
{
argv[1] instance;
}
みたいなの。
>>252
そのコードは根本的に間違ってるとは思うが。

文字列から対応するオブジェクトを生成させるために新しいオブジェクトを返す
関数ポインタや関数オブジェクトをstd::mapに格納するつーのはあるが。
>>252
int 値を受けて、実際のクラスを作るファクトリクラスを用意。

class Base;

class Factory {
public:
  typedef Base* (*FACTORY_METHOD)();
  void addClass(int class_id, FACTORY_METHOD f);
  Base* CreateInstance(int class_id);

  // singleton
  static Factory& GetInstance();
};

#define g_factory (Factory::GetInstance())

で、こいつに派生クラスのインスタンスを作成するメソッドを順次登録していく。

static Base* Create1() { return new Inheritance1; }
static Base* Create2() { return new Inheritance2; }

g_factory.add(1, Create1);
g_factory.add(2, Create2);
...

もちろん、手作業で Create1 とか g_factory.add() なんてのを書き並べていくのは
ダサイから、そこはマクロと static 変数を使って小細工する。
255252:03/12/16 01:28
Base = new って間違えてましたね。すいません。

>>254 ありがとうございます。眠いので明日やってみます。
よければ、そのマクロとstatic変数を使った小細工も教えてくだされ。
#include <iostream>
#include <loki/typelist.h>
#include <boost/shared_ptr.hpp>
template<typename TList,typename _Base>class FactoryImpl{
private:
  typedef _Base Base;
  template <typename TList2,typename Base2> friend class Factory;
  template <typename TList2,typename Base2> friend class FactoryImpl;
  static Base * Create(){return new typename TList::Head;}
  template <typename TList2>
  static inline void Init(Factory<TList2,Base> * factory,unsigned int ID){
    factory->m_factoryfn[ID]=Create;
    FactoryImpl<typename TList::Tail,Base>::Init(factory,ID+1);
  }
};
template<typename _Base>class FactoryImpl<Loki::NullType,_Base>{
private:
  template <typename TList2,typename Base2> friend class FactoryImpl;
  template <typename TList2>
  static inline void Init(Factory<TList2,_Base> * factory,unsigned int ID){}
};
template <typename TList,typename _Base>
class Factory{
public:
  typedef _Base Base;

  template <typename TList2,typename Base2>friend class FactoryImpl;
  Base * (*m_factoryfn[Loki::TL::Length<TList>::value])();
public:
  Factory(){
    FactoryImpl<TList,Base>::Init(this,0);
  }
  Base * Create(unsigned int id){
    return m_factoryfn[id]();
  }
};
class Base{public:virtual void print()=0;virtual ~Base(){}};
class Test0:public Base{public:void print(){std::cout << "Test0\n";}};
class Test1:public Base{public:void print(){std::cout << "Test1\n";}};
class Test2:public Base{public:void print(){std::cout << "Test2\n";}};
int main(){
  typedef Factory< TYPELIST_3(Test0,Test1,Test2) ,Base> Factory;
  Factory factory;
  boost::shared_ptr<Base> p(factory.Create(1));
  p->print();
  std::cin.get();
  return 0;
}

いぜん作りかけたやつだけど、LokiにもFactoryあるし。
FactoryそのものはLokiのやつ使って登録だけ楽に出来るユーリティーにしてもいいかな。
このぐらいだとFactory作る手間よりもとのコードに case 加えてるほうが
シンプルで間違いにくくて手間も少ない、よねえ。
260259:03/12/16 02:43
factory は作る。中身は元の switch 突っ込む、が正しいか。
>>259
クラス増えても
typedef Factory< TYPELIST_20(Test0,Test1,Test2,Test3,Test4,Test5,Test6,Test7,Test8,Test9,Test10,
  Test11,Test12,Test13,Test14,Test15,Test16,Test17,Test18,Test19) ,Base > Factory;
Factory factory;
factory.Create(19);

ついでに
template <typename T0,typename T1=Loki::NullType,typename T2=Loki::NullType>
struct GenTypelist{
  typedef Loki::Typelist<T0,typename GenTypelist<T1,T2,Loki::NullType>::Result> Result;
};
template<>
struct GenTypelist<Loki::NullType,Loki::NullType,Loki::NullType>{
  typedef Loki::NullType Result;
};
これのもっと数増やしたやつ使えば数字入りマクロ使う必要もなくなるし。
262デフォルトの名無しさん:03/12/16 13:57
std::vectorとboost::arrayの中間の機能のものを探しています。
あらかじめ上限が決まっていて、newやdeleteを呼び出さないvectorが欲しいのですが、
どこかにあるでしょうか?
>>262
即興で書いてみたがこんなの?

template<typename T, int SIZE> class fixed_array {
T v_[SIZE];
public:
typedef T * iterator;
typedef const T * const_iterator;
typedef size_t size_type;
const_iterator begin() const { return v_; }
const_iterator end() const { return v_ + SIZE; }
iterator begin() { return v_; }
iterator end() { return v_ + SIZE; }
size_type size() const { return SIZE; }
T& operator [](int index) { return v_[index]; }
const T& operator [](int index) const { return v_[index]; }
T& front() { return v_[0]; }
T& back() { return v_[SIZE-1]; }
// 以下適宜
};
>>263
そりゃ、まんま boost::array でんがな。
265デフォルトの名無しさん:03/12/16 14:23
error C2018: 文字 '0x40' は認識できません。
このエラーってどうして出るの???
>>265
「C2018」でぐぐれ
全角スペース (SJIS で 0x8140 だっけ?) とかがソースに混入してるんじゃないの?
>>262
std::vectorを最初にresizeでメモリ確保してして、push_back使わなければいいだけでは?
ていうか、上限きまってるならboost::arrayで十分だと思うんですが?
269デフォルトの名無しさん:03/12/16 17:55

LAN内にある他のパソコンに接続されたUSBカメラの動画を
リアルタイムで表示させたいのですがどのようにすればいいでしょうか?
ヒントや関連サイトなどありませんでしょうか
270262:03/12/16 19:19
>>268
最初の1回すらnewを呼ばせたくないけど、push_back()は使いたいんです。
上限超えたpush_back()は例外投げるしかないでしょうね。
boost::arrayって上限固定ではなく、サイズ固定ですよね。
自前で書いても良いのですが、車輪の再発明をして恥を書く前に聞いてみたわけです。
組み込み系やコンシューマーゲームでは需要があるかも。
>>270
boostに上げてくれると最高
capacity固定でsize可変ってことですよね?
ちょっと考えてみましたが、少なくとも
std::vectorやboost::arrayを使った実装はできませんね。
というわけで、自作が一番ええんやないかな。
boost::arrayをstd::vectorっぽく改造するのが一番手っ取り早そうだな。
>>270
> 最初の1回すらnewを呼ばせたくない
std::vecotr の第二引数でアロケータを指定できるが (標準だと std::allocator が使われる)、
これを自作のものに差し替えれば。
> また、テンプレートライブラリ(STL含む)に関する質問は
> 専用の別スレへどうぞ。
ttp://pc2.2ch.net/test/read.cgi/tech/1066493064/l50
277252:03/12/17 00:34
>>256>>257 ありがとうございます。
#include <loki/Typelist.h>
template <typename TList,typename _Base> class Factory; //前方宣言
の修正加えたら動きました。悲しいかな意味がよく分かりませんが・・・
取り敢えず、Typelistでも追ってみます。
ある規定クラスBから派生したクラスD1,D2,D3,D4があるとして、
これらを(何でもいいですが)コンテナクラスに格納してるとします。

で、ファイルにこれらの格納されている要素を
それぞれのクラスごとに形式を決めて書き出したとして、
読み出し&再生成&再格納する際は結局
その形式(クラスごとのIDなど)でswitch-caseするしかないんでしょうか。

仮想コンストラクタの例で上のような仕事をするメンバ関数について
More Effective C++などでも若干触れられていますが、
詳細な実装についてはまったく言及されていません。

switch-caseしてしまうと、クラスD5,D6...と形式追加されたときに
この仮想コンストラクタもメンテせねばならず、
オブジェクト指向っぽくありません。

玄人の皆さんはどのようにクラス設計されているのでしょうか?
>>278
んー? ちょっとまって。
確認しておきたい。

コンテナクラスに格納ってのは
同じ基底クラスのコンテナにポインタ使って格納してるの?

逆に、クラスごとに形式を決めて描き出す、ってのは
クラスごとに別のファイルに書くのか、
クラスごとに別々にブロック分けされてるのか、
それともコンテナ内での順位を保ったまま
無秩序に(実際のクラス関係なく)吐き出されてるの?

どうも自己完結気味に書かれてて
若干意図が読みとりにくいんだけど。
>>278
MFCのCObjectのシリアル化が参考になるかも
281278:03/12/17 01:40
まだコーディングし始めたわけじゃないんですが、

>>コンテナクラスに格納ってのは
>>同じ基底クラスのコンテナにポインタ使って格納してるの?

そのとおりの実装を想定してます。

>>逆に、クラスごとに形式を決めて描き出す、ってのは

については最後の

>>それともコンテナ内での順位を保ったまま
>>無秩序に(実際のクラス関係なく)吐き出されてるの?

に該当します。1ファイルにコンテナ内の順序を保ったまま
吐き出すことを想定しています。

説明不足気味で申し訳ない。

>>280

処理系がVC++じゃないんで、MFCは参照できないですねー。
シリアル化(シリアライズ)ってよく目にしますけど、どういうものですか?
シリアル化って日本語で言うんだ。
そのままシリアライズって言ってた。
どれくらい高レベルのシリアライズを要求してるのかね。

正直ファイルに書かれた時点で型情報失うんだから
なんらかの識別子は必須なんだけど、、、それわかってるのかなあ。
詳細詳細言う割には自分のクラスのファイル出力のことが抜け落ちてやしない?

さらに言えば
識別子を含めてファイルフォーマットを管理する
クラスを挟む必要があるわけだし。
もちろんそいつ自身がアブストラクト・ファクトリであってもいいけれど
すでに型情報があるのならそこからクラスごとのファクトリメソッドを呼べばいいわけで
その時点で引数までに共通性を求める仮想コンストラクタを要求する必要がなくなってしまうという話。
ああ、高レベルさってのはさ、たとえば
たとえばファクトリメソッドの中でファクトリメソッドを呼び出す処理をする必要があるのかとかね。
つまり、
Class A
{
SubA1 sa1_;
SubA2 sa2_;
public:
A(SubA1 sa1, SubA2 sa2)
: sa1_(sa1), sa2_(sa2) {;}
}
みたいなクラスがあったときは当然深いコピーがいるでしょ?
メンバがすべて基本型だという保障があるか、
クラスのコンストラクタが含めてすべて引数が基本型になっててメンバの面倒までみる
( A(double m11, int m12, char m21) : sa1_(m11,m12), sa2_(m21) {;} みたいに)
のならこんなことは考えなくてもいいわけだけど。
具体的なのフォーマットはたとえば
高レベルな場合、
(A
(SubA
(double 1.0)
(int 1024)
)
(SubB
(char 38)
)
)
低レベルかつ引数の型が固定の場合なら
A 1.0 1024 38
なんかでいい。
もちろん引数を読む前に型識別子がいる。
285278:03/12/17 02:59
>>282-284

長文解説ありがとうございます。
で、個人的には詳細な実装を求めているわけではなくて、
278にも書いたとおり、ファイルからの読み込み+インスタンスの再生成
ではswitch-caseに頼るしかないのか否か、ということです。

>>正直ファイルに書かれた時点で型情報失うんだから
>>なんらかの識別子は必須なんだけど、、、それわかってるのかなあ。

識別子を書き出すということは278でも書いているのですが、
この値を元にインスタンスを再生成ということは、
やはり switch-case で実装するということですか?

#>>284でファイルフォーマット例を挙げておられますが、
#たとえばこれを読み込むメソッドがどう実装されるのか、
#switch-caseを使ってA,A',A''を生成することのなるのか、
#A'''があたらに追加された場合、読み込む箇所も変更が
#必要となるのかが知りたいわけです。
286278:03/12/17 03:07
ちなみになぜこんなことを気にしだしたのかといえば、
書き込みの場合は格納されるクラス群に
例えばWriteMyself(...)の様な仮想関数を実装しておけば、
あとはコンテナの要素をそのまま全部なめながら
このメソッドをコールすれば済むのに
(もちろん新しいクラスを追加しても問題なし)、
読み込みはそうはいかないな、と考えたのが発端です。

#またわかりにくいですかね?
ああクラス側で読み書きをそれぞれ分散して管理したいのか。
シリアライズの場合は一カ所に集めた方がいいと思うけど。

そういうことだったら
std::ofstream& operator << (std::ofstream& fin, const SomeClass& something);
に対して
virtual
std:oifstream& SomeClass::ofstream& Write(std::ofstream& fout) {
return fout << *this;
}
を用意して仮想化してやるように

std::ifstream& operator >> (std::ifstream& fin, SomeClass& something);

virtual
ifstream& SomeClass::ifstream& Read(ifstream& fin) {
return fin >> *this;
}

とやればできるんじゃない?
ただこのまま使うとデフォルトコンストラクタ呼んだ後に代入することになっちゃうけど
>278
書き込みについては仮想関数で一発だけど、
読み込みについては、何らかのID->クラスのマッピングは
必要になる。(switch-caseはそのマッピング実装の一つ)
x86 で long double って何bitですか?
>>289
sizeofすればわかるだろ
CPU的にはIA-32では単精度32bit倍精度64bit拡張精度80bit。

ただしVC++の場合は32/64/64だったりするのでx86一般の話は不可能。
>>291
そうですか。gccだとどうなんだろ。sizeofしてみるか
>>285
> 278にも書いたとおり、ファイルからの読み込み+インスタンスの再生成
> ではswitch-caseに頼るしかないのか否か、ということです。
必ずしも switch - case で実装する必要はない。たとえば、非ローカル static オブジェクトを
利用して main 実行直前に ID -> クラスの対応表を作成する方法がある。

いまバイト列を読んで、B の派生クラス D1, D2, .. を実際に復元する関数を

 B* CreateD1(void const*); B* CreateD2(void const*);

としよう。まずは、これと ID の対応付けを行うクラスを用意する。各 ID は 128bit ぐらいの
長いデータにして、絶対に重複しないアルゴリズムを使って生成し、D1, D2, ... 各クラスに
static const メンバ変数として定義しておくのが良い。

typedef unsigned long long B_CLSID_TYPE; // D1, D2, ... 各派生クラスの固有 ID
typedef B* (*B_CREATOR_TYPE)(void const*); // D1, D2, .. 各派生クラスを new する関数

class BFactory {
public:
  // 復元関数を登録する
  void add(B_CLSID_TYPE magic, B_CREATOR_TYPE create_func);
  // ID からクラスを特定して、オブジェクトを復元する, 事前に add() で登録した関数を呼べば OK
  B* create(B_CLSID_TYPE magic, void const* data);
  // singleton
  static BFactory& GetInstance() { static BFactory factory; return factory; }
};

#define g_BFactory (BFactory::GetInstance())
294293:03/12/17 21:05
これで、後は誰かが

 g_BFactory.add(1, CreateD1);
 g_BFactory.add(2, CreateD2);

とか呼んでおけば良いわけだ。

ここで D1, D2, ... それぞれの派生クラスを実装しているファイル d1.cpp, d2.cpp に
次のようなクラスと変数の定義を付け加える。

struct D1AddToFactory {
  D1AddToFactory() {
    g_BFactory.add(1, CreateD1);
  }
};

static D1AddToFactory d1addToFactory;

これで main 実行前に static 変数 d1addToFactory が構築され、そのコンストラクタで
BFactory クラスのシングルトンインスタンスに D1 クラスの ID, オブジェクト生成関数が
対で登録される。

main 関数が実行されたときには、すでに g_BFactory.create() で、シリアライズした
オブジェクトが復元可能になっている。
295デフォルトの名無しさん:03/12/17 21:07
まだ作りかけだけどLokiのFactory用のユーリティを作ってみた。
ttp://do.sakura.ne.jp/~junkroom/cgi-bin/megabbs/readres.cgi?bo=lounge&vi=999294620&res=114&fi=no

生成されるクラスがBaseImplから継承する必要があること、IDに今のところint型とかしか使えないこと、などの制限はあるけど。
仮想関数GetClassIdが半自動でインプリメントされるようになっている。
使い方としては
class Base:public BaseRootImpl<int>{
public:
    virtual void print()=0;
    //typedef int IdentifierType;
    //virtual int GetClassId()=0;
    //virtual ~Base(){}
};
class Test0:public BaseImpl<Test0,Base>{
public:
    void print(){std::cout << "Test0\n";}
};
class Test1:public BaseImpl<Test1,Base>{
public:
    void print(){std::cout << "Test1\n";}
};
int main(){
    Loki::Factory<Base,int> factory;
    FactortyRegister<GenTypelist<Test0,Test1>::Result>(factory,0);//2つ目の引数からタイプリスト内のIDが連番で登録される、さらにgetClassIdが使えるようになる
    boost::shared_ptr<Base> p(factory.CreateObject(1));
    p->print();
    return 0;
}
出力ストリームに対して<<演算子をオーバーロードしたのですが、??なことが発生しました。
先輩方、原因が何か御教授願えますでしょうか・・・? 長くてすみません

状況: myclassを定義。myclass同士の和、myclassの出力(std::cout)に関し演算子をオーバーロード
症状: 和、出力ともに単体で正常動作。しかし「和を出力」しようとするとギタギタに怒られる
環境: g++ 3.3.1 (on cygwin)
ソース:
#include<iostream>
class myclass { public: int x,y; };

myclass operator+(myclass &c1, myclass &c2){
myclass t;
t.x = c1.x + c2.y; t.y = c1.y + c2.y;
return t; }

std::ostream& operator<<(std::ostream& os, myclass &c1){
os << "x: " << c1.x << std::endl; os << "y: " << c1.y << std::endl;
return os; }

int main(void){
myclass m1,m2,m3;
m1.x = 100; m1.y = 101; m2.x = 102; m2.y = 97;
m3 = m1 + m2;//問題なし
std::cout << m3;//問題なし
std::cout << (m1+m2);// めちゃめちゃ怒られる
return 0; }
>>296
× std::ostream& operator<<(std::ostream& os, myclass &c1){
○ std::ostream& operator<<(std::ostream& os, const myclass &c1){

ついでに
× myclass operator+(myclass &c1, myclass &c2){
○ myclass operator+(const myclass &c1, cosnt myclass &c2){

関数の中で引数に変更を加えないなら、全部const参照にすること。
でないと、constオブジェクトとか一時オブジェクトとかを使えなくなる。
298278:03/12/18 01:28
>>287

むー、でも、この仮想関数Readを呼び出すインスタンス
はどうやって決めればいいのでしょうか?というか、そこが肝なんですが。
なんか解釈が間違ってます?

>>288

端的な回答ありがとうございます。コストとリターン、やりたいことの
兼ね合いも考えて、>>293-294のソースも参考にしつつ実装方針を
決めることにします。

>>293-294

ひゃー、詳細な解説ありがとうございます。
中身を見て、参考にさせていただきます。

ありがとうございます。いつか恩返しできればいいのですが。
仮想関数呼び出しをするということは
その時点でクラスが構築されていないといけない。当たり前。
仮想関数を呼び出してる時点で
事前にその型のインスタンスの割り当てと初期化は行われている。
これが行うのはあくまで値の設定部分のみ。

クラスごとにシリアライズ用のメソッドを用意した場合の利点は、
READとWRITEの書式(当然復元可能である必要がある)を
クラスごとに管理できるってことの方。
マッピングはそれ以前に別のオブジェクトやら関数で行う必要があるって
再三言われてるんだけどまだ納得していなかったのか。

だいたい
クラスAの出力 10, 2.0 と
クラスBの出力 10, 2.0 を
それ単体で区別するなんて常識で考えても不可能でしょうに。

ちなみにマッピング方法はC++じゃ
>>293が挙げてるようなファクトリクラスを作るのが一般的だけれど
クラス自体がオブジェクトとして振る舞えて動的束縛に強い言語なら
また別なオブジェクト指向らしいやり方も存在する。
C++でも仮想クラスメソッドが持てればいいんだけどねえ……
300296:03/12/18 12:36
>>297
うまくいきました!どうもありがとうございます。
お教えに従いまして、意識してconstを使うように致しますです。
そんなことよりX'masって「'」はつけないんだけどね・・・
正しくはXmas。
そこの君。知ったかぶって恥をかかないようにね。
Xmas の X は実はギリシャ語のカイである。
ギリシャ語でのクリスマスの頭文字である。
それを聞くと一見 X は略になってるから
アポストロフィを付けても良さそうである。
しかし、Xmas は Christmas を直接略したものではないので、
アポストロフィはつけないのである。
だから、Χ'μασ なら許されるかもしれない。
>> そんなことよりX'masって「'」はつけないんだけどね・・・
ソースを示せ。
ヘー(・∀・)⊇
常識じゃん。
Xmasを辞書で引けば書いてる。
俺の辞書にXmasなんて文字は存在しない
俺のカレンダーにもない。
つーかXmasは文字じゃなくて文字列だろ。
Xmasなんて書くのは日本人だけ。
他の国ではきちんとChristmasと書いている。
http://user.auctions.shopping.yahoo.com/user/schmoo39sgreatdeals4u
この季節は日本人大もうけだなw
  \|/
  /⌒ヽ  / ̄ ̄ ̄ ̄ ̄ ̄ ̄
 │ ゚Θ゚)< そうでもないよ
 │ ∵ つ  \_______
 │ ∵ │
  \_/

>>311
http://search.yahoo.com/search?p=xmas
俺の辞書にはクルシミマスと言う単語ならある。
殆どの人は Xmas か X-mas と書く。
外国でも英語圏でなければ X'mas と書く人も見かけるけど。
毒男板か、ここはw
殆どの人は XMEN か X-MEN と書く。
外国でも英語圏でなければ X'MEN と書く人も見かけるけど。
318デフォルトの名無しさん:03/12/20 03:56
本を読んでると

inline istream& operator>>(istream &io, String &s)
{
  const int limit_string_size = 4096;
  char inBuf[limit_string_size];
  io >> setw(limit_string_size) >> inBuf;
  s = inBuf;
  return io; // String::operator=(const char*);
}

というソースがあったのですが
こういう場合inBufの確保にnewを使わないのはdeleteしなくていい他に何か理由があるのでしょうか?
>>318
スタックの上限に十分収まり、入力される文字の上限が
プログラム時に決まっているのなら静的配列で構わん。
staticにしないとバッファが使い回せないという問題はあるが
まだそんなことを気にする段階ではないようだし。

もひとつおせっかいすると
newで確保するのも根本的な解決にはならないぞ。
実行時に指定されたデータ数分だけ最初に確保したら
それ以降の自動的な拡張は行われないからな。

一時的にストリームから読み込んで何やらしたいのなら
streambufを使うのが常道。
せめてstringやvector<char>なんかを使った方がいい。
というかストリームからchar配列に指定文字数読み込むのにそんな書き方……。
学習進度にもよるが、get/getline/readなんかを文字数以外の終了条件に応じて使うことを勧める。
321318:03/12/20 07:10
詳しいレスありがd。
ストリーム読み取りに他の王道があるというのはとりあえずおいておいて

>>319-320
ということはnewでメモリを確保するのに比べて

char inBuf[limit_string_size];

は、書くのが楽な以外にメリットはないってことでしょうか?
結構ちらほら見るので何か理由があるのかなーと思って。
スタックの上限もあることだし、デメリットだけなのかな・・・。
>>321
ふつうは、実行時のパフォーマンスがいい。
あと、例外安全。
1.スタックよりヒープの方が確保/解放等にコストがかからない。
2.newは失敗する可能性を常に考慮にいれないといけない。
3.newで確保したメモリは必ず解放しないといけないが、
  複数のreturn文や内部のプロセスで例外が投げられたときに
  解放し損ねてリークすることがある。
勘違いしているようだが静的確保で済む場合は静的確保がデフォ。
>>323
1は逆じゃない?
3はスマートポインタに突っ込んどくと楽。
>>324
あ、ホントに逆だね。サンクス。
3のリソース管理は本当に必要ならスマートポインタ使うべきだけど
今回のようなものならそもそもSTLのコンテナなんかを使うべきところでしょう。
それに半端に勘違いしてstd::auto_ptrとか使うとdelete[]とdeleteの違いで
かえって困ることになりかねないから書かなかった。
>>322
>あと、例外安全。

まず、漏れも人のことは言えんと白状しておく。

newの失敗を気にするくせに
スタックのあふれは考えようともしないのは
非科学的だと思う。

スタックの最大使用量をきっちり計算して
定義ファイル書いてる香具師どんくらいいる?
つーかきちんと考えてるならローカルにバッファなんて作らないと思う。
問題の前提崩れてしまうぞ。
一元的に確保したものをplacement newや類似の仕組みで
切り分けたり使い回したりしない?
釈迦に説法かもしれないけど。
>>326
> スタックの最大使用量をきっちり計算して
全体を通しての計算はしていない。

再帰呼び出しが発生する部分だけ見積もりをとり、あと実機で動くプログラムに
細工してスタック使用量を実行時にモニタリング。最後に、その数値を使って
スタックファイル調整してる。
スタックオーバーフローなんて気にしたことなかったなぁ…。
#include <iostream>
void foo(int x){
  try{
    foo(x+1);
  }
  catch(...){
    std::cout << "exception at " << x + 1 << std::endl;
  }
}

int main(){
  foo(0);
}

試しにやってみたら、ちゃんとスタックオーバーフローするのな。
>>328
なるほどなー
テスト後にコア吐かせるかdiagモードでリブートしてRAMのケツをタシーロとか
スタックチェック埋め込んどいてあぼーん確定らしいときは守りに入るとか...
GUI使ったアプリをそろそろ作りたくなってきました
C++の開発環境を導入しようと思うのですが
現在VC++7.1とBorlandC++builder6.0で悩んでいます
両方使ったご経験のある方それぞれの長所をご教授ください
332318:03/12/21 02:02
いろいろレスありがとうございます。
まとめると

・スタックに確保は実行時のパフォーマンスがいい。
・newもスタックに確保する場合も失敗する可能性を常に考慮にいれないといけない。
・newで確保したメモリは必ず解放しないといけないが例外処理がめんどう。

そこで普通は

・スマートポインタやplacement newを使う。

placement newって知らなかった_| ̄|○
基本くさいなのに。

セキュリティ的には固定長バッファをスタックに積むだけであぼんな可能性を常に考慮しなくてはいけないし
かつ、マの負担を考えても前時代的な手法と思っていたのですが
ソースを見るといっこうに減らないので単に漏れが知らない何か理由があるのかな?と思ったわけです。
組み込み系を書いてる人はまた違う意見持ってそうなのでちょっと聞きたかったかな。
>>331
C++Builderは事実上死んだ(C++BuilderXはほとんど別物)んで
わざわざ買うならVC++のほうがいいとは思うが、そもそも趣味でやる程度なら
BCCやMingw(どっちもC++BuilderX Personalに入ってるが)で適当なGUIライブラリ
(それこそwxWindows)でもつついてりゃいいんじゃないか?
winny2もC++Builderで作ったらしいね
GUIをさっくり作りたいんなら今でもC++Builderはオススメですよ。
可能なら両方買っておきたいけど。

C++のクラスのprivateメンバに文字列定数と
RECT構造体の定数を含ませたいのですが、

class hoge {
   static const char strName[] = "おまえモナー";
   static const RECT rectangle = { 100, 100, 200, 200}
};

これですと、エラーになってしまいます。

const や static にこだわらずに、一般の変数として
宣言してコンストラクタでデフォルト値を代入すれば
問題ないと思うのですが、せっかくなので const
や static をつけたメンバ変数を宣言(定義?)すること
はできないのでしょうか?

stroustrupの本ではstatic constは整数にだけ認められて
いるみたいです。
(例)
class hoge {
  static const int = 100;
};

クラスに固有の文字列定数を持たせたい場合には
どうしますか?
337デフォルトの名無しさん:03/12/21 14:25
>>336
   static const RECT rectangle = { 100, 100, 200, 200}
この部分、最後に ; が付きます。

どっちにしろエラーですが。
>>336
・constでもコンストラクタの初期化記述で書ける
class hoge {
 const std::string strName;
public:
 hoge():strName("おまえモナー") {}
};


・staticなら初期化文は別途モジュール作って定義する
//hoge.h
class hoge {
 static const std::string strName; // 外部リンケージ宣言
};
//hoge.cpp
const std::string hoge::strName = "おまえモナー"; // 実体定義
>>336
template<char* s>class StrTaker{};
const char hoge::strName[] = "(*゚ー゚)ダッコ♪";
341デフォルトの名無しさん:03/12/21 14:46
>>338
なるほど。ありがとうございました。
実体定義のときには static は付けてはいけないのですね。

以下のようにchar配列を使っても、エラー無しでコンパイルできました。

#include <windows.h>

class hoge {
   static const char strName[];
   static const RECT rectangle;
};

const char hoge::strName[] = "おまえモナー";
const RECT hoge::rectangle = { 100, 100, 200, 200 };

>>341
え。常識じゃん。
> 実体定義のときには static は付けてはいけないのですね。

「staticなら初期化文は別途モジュール作って定義する」って書いてあるのに、
なんでそうなるんだ。
class A
{
#include <pshpack1.h>
public:
 struct B
 {
  char x;
  int y;
 };
#include <poppack.h>
};

A::Bだけアライン変更してます。
VC++6.0でコンパイルできましたが、これは言語規格的にいいのでしょうか?
#include がクラス宣言内で出てくるのは今まで見たこと無いので自信ないです。
#include自体は問答無用で内容ぶちまけるだけだから問題はない。
アライン云々は実装依存なので規格上はしったこっちゃないな。
>>345
>#include自体は問答無用で内容ぶちまけるだけ
納得しました。ありがとう。
>>346
ttp://www.tietew.jp/cppll/archive/5730
こんな使い方もありです。
348331:03/12/21 23:56
333さん334さん335さん
ご意見と情報ありがとうございましたm(__)m
349デフォルトの名無しさん:03/12/22 18:37
23日の夜を、クリスマスイブイブって得意顔で言うおっちゃんっているよなw
いるか?

☆★☆★★☆ラッキーレス☆★★☆★☆

    ⊂⊃     .☆.。.:*・゜
(\ ∧_∧   /
(ヾ ( ´∀`)/ このレスに出会ったあなたは超ラッキー。
''//( つ ● つ
(/(/___|″ 近々幸運が舞い込んでくることでしょう。
   し′し′    

☆★☆★★☆ラッキーレス☆★★☆★☆
>>349自身のことではなにの?
VC++6.0の場合

void func()
{
 AAA a1, a2;
 BBB b1, b2;
}

とした場合、スコープから抜けたときデストラクタが呼ばれる順序は
生成順の逆b2, b1, a2, a1となりました。
また、

class CCC
{
public:
 AAA a1, a2;
 BBB b1, b2;
};

CCC c;

とした場合も、cがスコープから抜けるとやはり生成順の逆
c, b2, b1, a2, a1の順でデストラクタが呼ばれました。

オブジェクトの解放順序は言語規則として定められているのでしょうか?
それともたまたまこうなっただけでしょうか?
決まってる
>>351
luckless かと思ったよ。
あるクラスの非constなメンバ関数へのポインタと、constなメンバ関数へのポインタの、
どちらも引数に取ることの出来る関数を書く方法はありますか?

例えば、以下の様なクラスと関数があったとします。

class foo
{
public:
void non_const_function() {};
void const_function() const {};
};

void f(void (foo::*pf)()) {}
void g(void (foo::*pf)() const) {}

この、f()とg()をそれぞれ以下の様な引数で呼ぶと、型変換が出来ないというエラーが出ます。

f(&foo::const_function);
g(&foo::non_const_function);

gcc 3.3.2でコンパイルしたときの具体的なエラーメッセージは次の様になります。

test.cc: In function `int main()':
test.cc:15: error: cannot convert `void (foo::*)() const' to `void (foo::*)()'
   for argument `1' to `void f(void (foo::*)())'
test.cc:16: error: cannot convert `void (foo::*)()' to `void (foo::*)() const'
   for argument `1' to `void g(void (foo::*)() const)'

この様なエラーメッセージが出るのですが、foo::const_functionとfoo::non_const_functionの
どちらも引数に取ることが出来るような関数を書くことは出来るでしょうか?
>>356
ポインタをconst付きにして、関数アドレスをconst_castして代入かな?
要はconstオブジェクトへの副作用が起きなければいいわけだろ
あ、それは無理か
失礼
>>356
テンプレートとかオーバーロードはだめなのかな?
360デフォルトの名無しさん:03/12/23 22:12
関数のローカル変数の参照をreturn;することって出来ませんか?
>>360
することだけならできる。
しかし、期待した結果は得られないだろう。

参照を返すんじゃなくて、
実体を返すか、
結果を格納するオブジェクトへの参照を引数から渡すようにすべし。
362360:03/12/23 22:27
>>361
レスありがとうございます。

関数の中でreturn;するローカル変数を作り上げて、
その実体を返した場合はメモリがちょっと無駄になりますか?
戻り値最適化が働くようにコンパイラとオプションを適切に選べば平気
ああただしローカル変数でもなるべく名前なしのものを返すこと。
どれだけわかりやすい記述で最適化がはたらくかはコンパイラ依存。
可能な限り return 文でコンストラクタ呼ぶようにした方がいい。

もし必ず参照で返したいと
いうのならヒープに new したものを返すしかない。
処理系依存を(特に最適化に関して)無限と読む痛い連中に注意
引数に出力先変数の参照を取った上でその参照を返す。
367360:03/12/23 22:44
コンパイラとかの問題になってしまうのですか?

ところで、関数
Classname function()
の中で大きいサイズのローカルなオブジェクト
Classname obj;
を作って、
そのままreturn obj;で返す場合は、
別のメモリ領域にそのobjの情報を作って、その関数の呼び出し元がそれを受け取って、
関数で使ったローカルなobjは消滅してしまう
って認識で合ってますか?
コンパイラと最適化次第やね。
369360:03/12/23 22:55
>>364
あれ、return文でコンストラクタを呼ぶってどういうことですか?
class A {
 A(int arg) {...};
};

A foo() {
 ...
 return A(4);
}

みたいな
371360:03/12/23 23:05
>>370
ありがとうございます。
その形式は初めて見ました。
それで望みのオブジェクトを返すには
コピーコンストラクタとか使えばいいのですか?
だから引数使えよ。
>A foo() {

アフォー
374360:03/12/23 23:18
return A(4);
みたいにやったら、A(4)しか返せないのではないですか?
関数内で計算したものを返せるのでしょうか。
void foo(A& a) {
 a.hoge();
}



A a;
foo(a);
生成後のインスタンスをいじって返すんだったら、ふつうにreturnするのが正解。
呼び出し元に返るときにコピーコンストラクタが使われる。
別にもう1つ渡したんでもいいと思うが...。
cin >> temp ;
while(cin.eof() == 0) {
  total += temp ;
  cout << "値を入力(終了はCtrl+Z)\n>> " ;
  cin >> temp ;
}
こんなコード書いて実行してみたら、
EOF(Ctrl+Z)を読み込んだ時点で、ループを抜けるどころか
プログラムまで抜けてしまい、終了してしまいます
こいつが原因なんですが、どこが間違ってますかね?
int foo()
{
 int x = 計算式;
 return x;
}

void bar()
{
 A a(foo()); // 計算結果からAを構築
}

コピーにかかるコストを抑えたくて参照で返すとか言ってるんだろうから
このていどのコードでOK

最適化の話を注意深く調べれば

inline const A foo()
{
 int x = 計算式;
 return x;
}

void bar()
{
 A a(foo());
}
で十分なことに気づくだろう
EOFをいれたきゃCtrl+D
UNIX板行ってもう一度利きなおして来い
Windows では Ctrl+Z だ。
382378:03/12/24 15:27
ぐぐったら自己解決しました
お騒がせしてすまんかった・・・
383デフォルトの名無しさん:03/12/26 01:13
お聞きしたいのですが…仮の話として

class A
{
 const int m_n;
public:
 A(const int n) : m_n(n){};
 int Get() const { return m_n; }
};

A aa[10]; // 何かしらコンストラクタに値が代入されるとします。

と、あったとして、
aa[i].Get() した値が、ある値を超えた所をfind_ifで探したい…
という場合の関数オブジェクトの作り方に悩んでいます。

bind2ndだけだと上手くいきませんし…
mem_fun系とかを使うことになるんでしょうが、どう絡めていっていいものやら…

自前で比較用の関数オブジェクトクラスを新規で作るしか、
方法はないのでしょうか?
>>383
標準ライブラリのmem_funとbind系だけでは苦しいかと。
Boost.Bindで
 bind( less<int>(), 100, bind(&A::Get, _1) )
  // 100を越えてればtrue、100以下ならfalse
>>383
#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace boost::lambda;
A* p = std::find_if(&aa[0], &aa[10], bind(&A::Get, _1) > 10);
>>383
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/counting_iterator.hpp>
#include <iostream>
#include <algorithm>
#include <vector>
class A
{
    int m_n;
public:
    A(int n) : m_n(n){};
    //A(){m_n=0;}
    
    int Get() const { return m_n; }
};
int main(){
    using namespace boost::lambda;
    using namespace std;
    vector<A> v;
    v.reserve(20);
    copy(boost::make_counting_iterator(0),boost::make_counting_iterator(20),std::back_inserter(v));//初期化
    for_each(v.begin(),v.end(),std::cout << bind(&A::Get,_1) << " ");//最初にあるデーターの中身を表示してみる
    cout << std::endl;

    //複数に分けて
    vector<A>::iterator p=find_if(v.begin(),v.end(), bind(&A::Get,_1) >5);
    vector<A>::iterator pend=std::find_if(v.rbegin(),v.rend(),bind(&A::Get,_1) <15).base();//->base());
    for_each(p,pend,std::cout << bind(&A::Get,_1) << " ");
    cout << endl;
    
    //1回でまとめて
    for_each(    find_if(v.begin(),v.end(), bind(&A::Get,_1) >5),
                find_if(v.rbegin(),v.rend(),bind(&A::Get,_1) <15).base(),
                std::cout << bind(&A::Get,_1) << " ");
    return 0;
}
今ほかに思いついたけどこんなのもあり、同じの書くの大変なので一部省略
#include <boost/lambda/if.hpp>
//...
int main(){
    //...
    for_each(v.begin(),v.end(), if_( (bind(&A::Get,_1)>5 )&& (bind(&A::Get,_1) <15))[
        cout << bind(&A::Get,_1) << " "
        ]);
    return 0;
}
389383:03/12/26 02:50
今まで boost 使った事無かったので、
VC7.1に入っているSTLだけで解決してようとしてました…

やはり、boost は使っていったほうが便利のようですね。
これから慣れていく意味でも、導入してみようと思います。


サンプルをいただけた >>384, 385, 386さん
ありがとうございます。
勉強させていただきます。
>>387-388
うむ、キミがBoost.Lambdaの使い方を覚えて嬉しそうなのはわかった。
 ・とりあえず std:: はつけるのかつけないのかどっちかに統一してくれ。
 ・なんで v が sort 済みであることを仮定した話題になっているのか。
 ・これでいいじゃん
boost::transform_iterator_generator<const_mem_fun_ref_t<int,A>, vector<A>::iterator>::type
  b( v.begin(), mem_fun_ref(&A::Get) ), e( v.end(), mem_fun_ref(&A::Get) );
copy( lower_bound(b,e,6), upper_bound(b,e,14), ostream_iterator<int>(cout," ") );
なんかこう、読みづらいな。
>>389
Boostのlambdaがまともに通るコンパイラでよかったね。
>>391
STLもBoostも一行にぎゅっと濃縮する傾向があるから
どうしても読みにくくなるねえ。
こんなのやり方わかる方いますか?
注意:以下のソース、コンパイル通らない
class CHoge1{
class CHoge2{
int m_Value2;//変数名を変える必要もないけどサンプルだし
public:
CHoge2(n){m_Vaue2 = n;}
};
int m_Value1;
const static CHoge2 m_ins[];
};

CHoge1::CHoge2 CHoge1::m_ins = {
CHoge2(3),
CHoge2(10),
};

やりたい事はクラスの中でしか使わないクラス型を作って、
メンバにstaticでその配列を持ち(実際のメンバは先頭のポインタ)
テーブルみたいに、それを使うってかんじなんですけど。
現状では、CHoge2のコンストラクタでエラーになってるみたい。
だいたいm_insの実体を作ってるところも間違ってる気がする。
少なくとも
CHoge1::CHoge2 CHoge1::m_ins = {
CHoge1::CHoge2(3),
CHoge1::CHoge2(10),
};
じゃないのか。
>>393
VC6 だと 以下でとおる。
const CHoge1::CHoge2 CHoge1::m_ins_a[] ={
CHoge1::CHoge2(3),
CHoge1::CHoge2(10),
};

あとは、スペルミス等直せばよし。
396395:03/12/26 09:30
俺が変数名間違ってどうするよ。
m_ins_a -> m_ins
>>393
とりあえずエラーメッセージを書こうぜ。
コンストラクタでエラーが出てるのは、
× CHoge2(n){m_Vaue2 = n;}
○ CHoge2(int n){m_Value2 = n;}
後は、>>375,376
レスありがとうございます。
無事解決しました。
スペルミスだとか型宣言の忘れだとか、とても恥ずかしいです。
>>398
もっと恥ずかしいのは自分でエラーメッセージを読まないことだな。
クラスのメンバ変数につける
constとstaticって順番どっちでも意味同じなんですか?
static const int m_Value;

const static int m_Value;
static const int
const static int
static int const
const int static
int static const
int const static
全部一緒
全部一緒だけど、あんまり変な書き方すると読みにくい。
static const 型名

で漏れは統一してる。
int const staticで統一してる人とかいるのかな?
すげー読みにくい気がする
つかバラバラなのが最悪
スコープに関する修飾詞はなんとなく前のほうにもっていくのが普通だね
記憶クラスは型じゃないから型を読むのを
妨害しないように(つまり左)に書いてる
constは本音ではint constと書きたいが
漏れの周りがconst intなので協調してる
漏れはclass derived : public virtual baseって書いてるけど
文句ある人の批判を聞いてみたい
つーか仮想継承しないし。
>>409
まったくだ(笑)
411デフォルトの名無しさん:03/12/27 17:08
基本的な質問でスマソですが、

class foo {
public:
  foo () throw(bar);
  class bar;
};

class foo::bar : public exception {
  int x;
};

以上のコードをコンパイラに通す方法は
どうやればいいんでしょうか?
bar の前に throw (bar) があるので、事前に
bar を宣言しないといけないのですが、

冒頭に
class foo;
class foo::bar;
とやってみたり、

class foo {
  class bar;
};
とやってみたりしましたが、いずれもエラーが
でてしまいます。
>>411
class foo {
public:
  class bar : public exception {
    int x;
  };
  foo () throw(bar);
};

>>412
もちろん、そういう解決法はあるのですが、
なんとか>>411の順番で通す方法は
ないものかと思いまして・・・。
throw(class bar)
>>413
>>412こそが普通だが。

class foo {
public:
  class bar; // 宣言を先に
  foo () throw(bar);
};
これじゃ通らないん?
>>414
これで通りました!
ありがとうございます。

>>415
なんとなく、例外で投げられるクラスをクラス宣言の
一番下にもっていきたいなと思いまして。あんまり
一般的じゃないんですかね。
>>416
ちなみに>>414>>415の2行をひとつにまとめたものね。
いきなり識別子を出してもそれが何であるかコンパイラには分からないので
まずそれがclass名であるということだけを先に宣言しておく。
>>409
ライブラリの仕様で決まってたりする

# 捨てろとか言うと恥かくぞ
# 笑う人たちはレスしそうにないが
>>418
設計のおかしいライブラリを使わざるを得ない状態ってやつか。
つまり、文句が出てくるほど使われていはない、ってことさ。
400だって、volatileとかsignedを何処に挟むか聞いてないだろ。
少なくともおまいらの知らない分野らしいことはよくわかったyo
最近は富豪的プログラミングがトレンドなんだろ、どーせ
static const volatile unsigned short int ax;
>>421ほど'yo'の似合わない文体は初めて見た。
extern static const volatile unsigned long long int val = ULLONG_MAX;

・C++にlong longないけどな……
・externとstaticって同居できたっけ?
const volatile は普通 extern だと思ったが
インラインアセンブラでどうにでもなりそうだし
どちらにしろ使ったこと無いので
どうでもいいや。
さらにresister修飾子も付け加えられる事に気づいたが、さらにどうでもいいや
register/static/externはそれぞれ排反しないかな?
意味がないだけでつけられるのか、つけてはいけなかったか覚えてないけど。
>>419
標準ライブラリだと iostream とか。

まぁ、使わないけどな。
>>428
漏れ使いまくってる。特にstringstream系とか。
別に使う分には設計おかしいとは思わないけどなあ。
派生しようとすると大変かもしれんけど。
>>429
stream 系は設計おかしいよ。
>>430
どういう点が?
operator>>/<<のことだろ
>>431
菱形継承してる点も、今から見るとちょっと…。
正直、10年C++やってるがiosよくわからない
使ってる手段だけで解ったような決まり文句を言い出す青二才とは接点がない
>>428 何使ってるの?
>>432
いまや >>/<< は入出力演算子です。
整数型だけ、シフト演算するようにオーバーロードされているのです。
>>437
へ?std::basic_ostreamのテンプレートクラスのメンバ関数
じゃないの?

すなわち
 std::cout << 1 << std::endl;

 std::cout.operator<<<int, std::char_traits<int> >(1) << std::endl;
と同じ。
439マジレスにマジレス:03/12/29 15:43
>>438
ちょっと違う。
メンバ関数で実装されてるのは組込型に対してだけ。
それ以外はグローバル関数としてオーバーロードされている/されることになる。
440マ(ry:03/12/29 15:51
>>439
#include <cstdio>
struct Ore_stream
{
    Ore_stream &operator<<(const char *str) {std::puts(str); return *this;}
};
一瞬OLE_streamかと思た
>>437
ああそういう事か。シフト演算子の左辺に整数型がある時は
シフトするという意味ね。
>>439
クラスのメンバは大抵privateにしておくので、入出力演算子
は大抵friendで宣言しておいて後からグローバルで定義す
るよね。
std::cout.operator<<<int, std::char_traits<int> >(1).operator<<(std::endl);
↑しかし読みにくいねえ。こんな風に書かなくて良くて良かったYO。
>>442
>大抵friendで宣言しておいて

んなことしねーよ
それじゃprivateになってないだろ
後から定義したグローバル関数に依存されちまう
>>444
そしたらどうやって書くの?クラスのメンバ関数で<<演算子の
定義はできないよ。thisはクラスオブジェクトを指すのであって、
std::ostreamは指してくれないよ。

ダメな例:

class Cls {
 int x;
public:
 std::ostream& operator<<(std::ostream& os, const Cls &c) const {
  os << c.x;
  return os;
 }
};

class Cls {
 int x;
public:
 std::ostream& operator<<(std::ostream& os) const {
  os << this->x;
  return os;
 }
};
良い例:

class Cls {
 int x;
public:
 friend std::ostream& operator<<(std::ostream& os, const Cls& c);
 Cls() : x(0) {}
};

std::ostream& operator<<(std::ostream& os, const Cls& c)
{
 os << c.x;
 return os;
}

これ以外に定義の仕方知らないんだが。他に良い方法が
あったら教えて欲しい。
>>445
それoperator<<よりdebugprintていう名前のほうがいいんじゃないの

俺は
std::ostream& operator<<(std::ostream& os, const Cls& c)
{
 os << c.public_get_value();
 return os;
}
例えばClsがstd::stringなら
std::ostream& operator<<(std::ostream& os, const std::string& s)
{
 os << s.c_str();
 return os;
}
>>447
なるほど、サンクス。という事はfriendはわざわざキーワードの
使い方を説明するために使って見せただけなのか。

そしたら

std::cout << c;

と書く代わりに

std::cout << c.public_get_value();

と書いても同じだね。friendはカプセル化手法に穴を開けるもので
ある事は知ってたけど、うまく使えば入出力関数を作らなくて済む
ので便利なものだと思っていた。
>>447
クラスの内部メンバの情報が public で見られるとは限らないから
たとえ出力演算でも friend 宣言がいることもあるんじゃない?
設計がデバッグ出力でなければ public な情報だけ見られりゃ十分ってのは理想じゃないかなあ……。

でも>>444のthis云々は意味がよくわからん。
もしかしてクラス内でグローバル関数を宣言する目的(だけ)で friend 宣言してるってこと?
ちなみに俺なら friend で宣言した場合にもグローバル関数ならアクセサメソッドを通すようにするが。
上書きがいやなら名前空間をしっかり管理しろと
少々話は逸れるけれど、
そのアクセサ public_get_value() も出力演算のためだけに追加したものなら
それのアクセサ自体を private/protected において出力演算を friend 宣言すべきかな?

本来出力以外では不要なアクセサが他に公開されるのは本末転倒な気がする。
しかし、こうしてしまうと別のストリームに対する入出力を追加したいときに
クラスの定義からいじらないけなくなる。

設計がしっかりしてりゃんなことないって言われりゃごもっともなんだが。
452デフォルトの名無しさん:03/12/30 17:09
プログラムの質問じゃないのですが申し訳ない。
VC++でビルドをかけるとよくリンクの途中で止まってしまいビルドの中止を選んでも止まりません。
しかたなくタスクマネージャから終了かけるのですが、これってなんとかならないでしょうか?
>>452
ハードが腐ってるんじゃないの? リンク処理は CPU, メモリに負荷を掛けるから
普段ギリギリの状態で動いているマシンだと死にやすい。
454452:03/12/30 17:42
>>453
そ、そうなんですか・・・?
結構新しいマシンなんですが…
部品変えるべきですか?
ハードディスクがいっぱいいっぱいとか。
456452:03/12/30 17:52
30G空いてます。

スペック
CPU:P4 2.8C
メモリ:DDR400 512M*2
HDD C:40G D:80G

メモリ*2がノーブランドなんですがこいつですかね?
メモリに負荷のかかる別のアプリ(自分で作ってもいい)を使っても
止まるようなことがあればメモリのせいかも。
>>456
memchk86は?
>>452
俺もクラスのメンバ増やしたり減らしたりしたときになることがある。vc6。
460貧乏紙:03/12/30 19:58
>>452
OSがwin98orMeじゃない?
461452:03/12/30 20:17
OSは2000proです。みなさんたくさんのレスありがとうございます。
警告がでる場合などに止まりやすいみたいです。
int a;
double b,c;

c = (double)a * b;

こういうことをする意味はあるのでしょうか?
実を言うとc#でやるんですが、これはコンパイラによって話が別なんでしょうか?
462です。

c = a * b;
と比べてという意味です。
こうした場合精度は失われるのでしょうか?
>>462
数値演算はオペランドの中でもっとも”大きな”型に自動的に格上げされる。
これは言語の規定であって環境依存はしない(C#はしらんがC/C++ではそう)。

その例の場合は a が自動的に double に格上げされるんで
明示的にキャストする必要はないから安心し。

double a = (double)5 / 3 * 0.5
みたいな場合は int 同士の除算が先にあるんで必要だけど。
>>464
遅レス申し訳ないです。

自分には大変勉強になりました。
下らない質問に回答頂きありがとうございました。
466デフォルトの名無しさん:03/12/30 22:42
教えてください。
CStringなどのクラスインスタンスをメンバに持つクラスを、
恐らく静的に作成したりZeroMemoryなどで初期化したりすると、
使用したときにエラーを起こしてしまいます。

vfptrが0に初期化されたからだと思いますが、
このvfptrを元に設定し直すと言う事はできるのでしょうか?

またはクラスメンバにそういったクラスインスタンスを持たせることはまずいのでしょうか?
動的に作成すれば問題はありませんが、クラスインスタンスは動的に作成するものなんでしょうか?


解決方法、というか一般的に取られている方法などがあれば教えてください。
具体的な作成プロセスがようわからんが、
インスタンスの初期化はコンストラクタで行うのが基本だ。
ZeroMemoryなんか論外。クラスのポインタ型メンバが 0 (NULL) にセットされりゃそりゃ落ちる。
468466:03/12/30 23:02
>>467
レスありがとうございます。
よく見たらコンストラクタでZeroMemory(this, sizeof *this);なんてやってました……。
データだけのインスタンスの時は確かに正常だったわけですが、
これで関数呼んだら確かに落ちますよね……。


個人的に疑問に思ったのですが、vfptrを再設定する方法というのはあるのでしょうか?
単純に他のインスタンスからコピーしてもダメみたいですが……。
469ヽ(´ー`)ノ:03/12/30 23:11
>>466
vfptr 弄ったりしちゃダメ。
なんで ZeroMemory なんか使いたいの?やりたい事言った方がいいと思う。
多分アプローチの仕方が間違ってるんじゃないかな。
vfptrは直接いじれるものでもいじるものでもない。

そういう場合は
Class BaseFunctionImpl() {
...
virtual BaseFunctionImpl* Clone() = 0;
virtual ~BaseFunctionImpl() = 0;
};

Class FunctionImplA : public BaseFunctionImpl() {
...
};

Class ClassA {
...
BaseFunctionImpl* fptr;
...
};

のように動的に割り当てたい関数だけを集約した抽象基底クラスへのポインタを
メンバとして持つようにする。
ヘッダーファイルで
using namespace std;
と書くのはよくないと思うのですが、普通は
どのようにするのでしょうか?

やはり、宣言は全てstd::をつけたほうが良いのでしょうか?
>>471
まあ、普通に全て std:: 付ける。
>>468
消す前にデストラクタを明示的に呼び出して、
ゼロクリア後に配置構文newを使えば大丈夫...つか、そんな事始めからするな。
>>471
inline 関数内限定でなら using namespace std; することもある。
>>471
インスタンスの型宣言に関してはローカルに typedef してエイリアスを作ってしまう。
関数に関しては、inline でない限りヘッダには書かないはずだし。
質問です。

固定長ファイルを読み込むときって、
皆さん、どんな風なプログラム書かれています?

31.412.2 2.132.1
23.1

↑みたいなファイルです。
(上の例だと5つとも全部小数第1位までの3桁の実数)
つーか namespace はオープンだからそこでグローバルに using したらやばいけど
関数内部やクラス内部のローカルスコープは外から参照できないんで使ってもそれほど実害はない。
478466:03/12/30 23:29
>>470
そんな大層な事をするクラスでもなかったもので……

>>469,473
いえ、クラスのメンバが多いので初期化をラクしたかったというか。
ただのデータホルダとして、構造体の代わりとして使っていたものに関数を追加したら
そうなってしまって。

あの、新たな疑問が浮かんできたんですが、
struct内で関数を宣言した場合どうなのるかな?と試してみたら、
structではZeroMemoryしても関数は呼び出されるのですね。

structとclassの違いを漠然と覚えていましたが、
よく分からなくなってしまいました……。
クラスのメンバメソッドはvfptrからアクセスするわけですが、
structの関数はどういう形でよびだされているのでしょうか?
479471:03/12/30 23:33
>>472, 474, 475
レスありがとうございます。
参考にさせていただきます。
classとstructは、デフォルトのアクセス修飾子が異なるだけで、全く同じもの。
>>478
正直君はvfptrとかを使うレベルに達していないようだが理解は正確か? とてもそうは思えない。
virtual でないメンバ関数はすべてコンパイル時に割り当てられる。インスタンスにその後は残らない。
メンバ関数を追加してsizeofの値を確かめて見ればわかる。

C++におけるstruct と class の違いは
指定なしのメンバのアクセス指定子と継承方法が public か private かくらい。

きちんとした違いは内部のデータ構造に現れる。POD = plain old data でぐぐってみろ。
482ヽ(´ー`)ノ:03/12/30 23:48
> いえ、クラスのメンバが多いので初期化をラクしたかったというか。
> ただのデータホルダとして、構造体の代わりとして使っていたものに関数を追加したら
> そうなってしまって。
それはイクナイ。

クラスのメンバは面倒でも一つ一つ初期化すべきだよ。
でないと、他の人がコード読んだ時に、何やってるかを一発で理解できないじゃん。
問題はいろいろあるが、
この場合の一番の問題は CString 型メンバを勝手にサイズ分ゼロで初期化したことだろ。
内部構造がわからんクラスインスタンスに対し(わかっていても)
そんな初期化方法は邪悪以外の何者でもない。

>>467でも書いたが原因はおそらく内部文字列へのポインタが NULL になって実行時エラーになってる。
仮想関数を用いていないようなのに vfptr 云々はどこから出てきたんだ?
struct T{
POD1 p1;int i,j,k;POD2 pe;
virtual ~T(){}
T(){ ZeroMemory( &p1, (char*)&pe - (char*)&p1 + sizeof(pe) );}
};
意味もわからずメンバをvirtualにしたり、仮想デストラクタをつけたりしてる場合もあるが..
この場合は、vtblは関係ない気がする。

ZeroMemoryやmemcpy, memsetといったCでよくやるメモリ操作はなるべく
使わないようにしなさいな。
C++のカプセル化を破壊するか、その後の拡張を阻害する要因になりがちだ。

Cあがりだと、明示的なキャストを使い続けるケースが多いけど、あれもどうにか
やめさせられんかねえ...
>Cあがりだと、明示的なキャストを使い続けるケースが多いけど、あれもどうにか
>やめさせられんかねえ...

_| ̄|○ スマナイ…
487デフォルトの名無しさん:03/12/31 01:53
Cの文法を理解したヤシがC++を始めるにあたり良い入門書ってないでしょうか?
易しすぎず、難しすぎずぐらいのもの。
できればCとの記述の違いも書いてくれていればなお良いんですが・・・。
>>487
http://pc2.2ch.net/test/read.cgi/tech/1072184936/
しかもその手の質問はさんざん既出
「CプログラマのためのC++入門」つー、まんまな本があるが俺はおすすめしない。
標準ライブラリに関する記述が完全に時代遅れなので。
つか、ISO標準化から5年も経ってるのに改訂されてない時点で捨てていい。

ある程度知識があるならいきなり「プログラミング言語C++」から入ってもいいと思うけどな。
>>487
このスレをpart1から読めばただでそこらに売っている本より理解を深める事が出来る
もしそれが嫌ならば自分で買って確かめるしかない。ちなみに日本人原作で良い本には
なかなかめぐり合えないでしょう。
そして、入門書なんてどの本も似たり寄ったり肝心なことが抜けてる
まだ入門書なんて探してるあたり
Cの文法が理解できたと言っているのを
あまり買いかぶらない方がよさそうだぜ
一度JavaをとlispあたりをかじってからC++に戻ってくれば?
>>481の言うとおり、>>466はvfptr云々のレベルではないね。
特に、CStringに対してZeroMemoryで初期化しているあたりを見ると
1)C++特有の約束事

2)オブジェクト指向的な考え方
のどちらも多分ほとんど身についてない。

1)に関してだと、たとえば
「内部で動的にメモリを確保するメンバがいたら、コピーコンストラクタ
と代入演算子はかならず自前で用意する」
などなどの基本事項は大丈夫?

2)に関して言えば、メンバに利用しているクラスなり構造体なりの
内部構造が変わったとしたら、ZeroMemoryしていいかどうかなんて
誰も判断できなくなる。だから、>>482の言うとおり、素直に初期化
を書くべき。Cでゴリゴリ書いてるんじゃないんだから。

上のことがちょっとでも理解できてないのなら、たとえCの文法がわかっていても
(というか、文法がわかっているのとプログラムが書けるということは本当は
全然別のことなんだけど)、>>487で書いているような無理はせず、きちんと
基本が書いてあるC++の本を読むべきと思う。正直、応用段階ではないよ。
それを読んだら、あとはEffective C++くらいは最低理解しておく。
POD struct なら ZeroMemory することはよくあるけどね。
>>494
漏れは滅多にしない。 代わりに

  PODstruct hoge = { 0 };

を多用する。てか、なんで Win32API を前提に話を進めてるんだ?
使うなら memset だろ。
>>495
そうだな。memset だ。
ポインタあるときは使わない方がいいけど。

コンパイラ(と警告レベル)によっては
PODstruct hoge = { 0 };
で警告出すこともある。
ところで>>476よ。
そろそろそのファイルのフォーマットを明らかにしてくれんかね。
まず空白文字による区切りがあるのかないのか
整数部分の桁数はいくつなのか
最低その2つがわからんと「固定長」の定義がわからん。

#科学表記による入力はどうだとか
#小数点は"."のみでなく","も含むのかとかもあるけど

どちらにせよそれだけのために自前の入力ストリームを作る気はしないな。
やってCの scanf 系列を使うかだ。
標準の istream に不満があるならそれも書いてくれ。
>>481
きちんとした違いとは何ですか
>>480氏の答えと時間差で遅れたのですか?
>>497
多分>>476は4文字づつ取り出して処理するって話かも。
まあ、いまどきそんなフォーマット扱うほうが珍しいとは思うが。
>>498
いや、問題はclassとstructの違いではなく
PODとそれ以外だ、という話なんでは?

で、それ以外(=classまたはstruct)だが
仮想関数が含まれるかどうかで違いはあるにしろ
現在ないからといってそれに依存するとあとで足したときに死ぬので
PODでないもの相手のときは常にmemsetとかで塗りつぶすのは厳禁と。
class と struct は C++ では基本的に同じものだけど、
やっぱり違う名前を使っている以上
使い分けはした方がいいと思うんだよね。
non-POD struct はなるべく作らないようにしてる。
まぁ、別の話ではあるが。

C++ ならメンバを 0 クリアするメンバ関数を作っておけば、
C ならメンバを 0 クリアするマクロか関数かを作っておけば、
memset にするかどうかを途中で変更できるんで、色々と楽ですな。
俺メモ

POD (Plain Old Data)
古き良き単純なデータ、というか何と言おうか。

詳細な定義は、ISO C++ 規格の 9.4 にてなされていますが、 ぶっちゃけ、ユーザー定義の代入演算子や
デストラクタやらを持たない、 memcpyなどでメモリを直にいじってコピーしたりして問題のない オブジェクトのこと。
>>501
標準ライブラリの作法ですでに
関数オブジェクトや traits なんかに struct が使われているのだから、
今更エンドユーザーが C-like な struct にのみ限定する意味が果たしてあるのか疑問だけどな。

オペレーターオーバーロードといっしょで宗教論争になってしまうが。
宗教論争は避けたいので
class と struct の使い分けに関してはここで 糸冬 了
ZeroMemoryはAPIに渡す構造体の初期化ぐらいにしか
使わない。
ZeroMemory って、memset をラップしてるだけのマクロなんだよね。
うん。そんでWTLの話だけど7.0から7.1に変わったら、
構造体の初期化がmemsetから{0}に変わってた。
>>502
あるデータ構造に対して、
それを直接処理する専用のハードウェアが用意されているとき、
そのデータ構造をPODという

・・・なんてのはどうだい?
どうだいもなにもここは(標準の)C++のスレであって勝手に俺定義を持ち出されてもな……。
仮にそういう名称を与えて何の役に立つ?
既存の概念の拡張にすらなっていないと思うんだが。
意味がよくわからんが、fpuがエミュだとfloat, doubleが
PODで無くなるのか?
PODと非PODに分類することの、そもそもの意図は?
>>497 >>499
あけましておめでとうございます。

479です。

31.412.2 2.132.1
23.1

フォーマットですが、499氏の言う通りで、
4桁ずつ取り出して処理する固定長データファイルで、
データ間に区切りは存在しません。
適当な桁数ごと(この場合は16桁ごと)に改行が入っています。
つまり、データとしては、「31.4」「12.2」「2.1」「32.1」「23.1」の5個です。
小数点は「.」で、小数表記は通常のものです(科学表記ではなくて)。
(この場合32.1の後で改行)

何をしたいか、というと、FORTRANのWRITE文で
作成したデータファイルをC++で読みたいのですが、何かいい方法はないかな、と思って。
続き。

FORTRANだと、この手のファイルは、

READ( 61,650 ) ( A( I ), I=1,X )
650 FORMAT( 4F4.1 )

のような形ですぐに読めてしまうんだけど、C++だと、
scanfを使う場合、4個分すべてフォーマットを記述しないとならないし、
最終行は4個データがあるとは限らないので、特別な処理を必要とします。

何かうまい書き方がないかな、と思って質問しました。

できれば、FORTRANで作成したデータファイルを読むことが多いので、
拡張してライブラリを作っておきたい、というのもあります。
# f2cだと、入出力と型がf2cに特化されていて、一般的なC++の
# プログラムで使いにくいので。
fortranで作ったプロシージャをCから呼び出すためのラッパーをアセンブラで作ったら?
fortran で作ったプロシージャは
C++ から単純に呼び出せる。

   procedure test(a, b)
    integer a, b
    a = b
    return
   end

#define FNAME(name) name##_ // このあたりはコンパイラによって変わるので #if で分岐してちょ
extern "C" void FNAME(test)(int& a, int& b);

int main() {
 int a, b = 3;
 test(a, b);
}

あとはライブラリをどうにかすれば OK 。
これも指定の仕方はコンパイラによって変わる。
>>513
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;

int main() {
 static const int PerLine = 4;
 static const char formatIn [] = "%4lf";
 static const char formatOut[] = "%8.2f";
 static const char Filename [] = "test.txt";

 FILE* file = fopen(Filename, "r");
 if(file == NULL) { return EXIT_FAILURE; }

 int total;
 do {
  double a[PerLine];

  for(total = 0; total < PerLine; ++total) {
   if(fscanf(file, formatIn, &a[total]) == EOF) { break; }
  }
  for(int i = 0; i < total; ++i) {
   printf(formatOut, a[i]);
  }
  puts("");
 } while(total == PerLine);
 fclose(file);
}
C 非互換のオブジェクトを extern "C" で呼び出した結果は未定義
extern "FORTRAN" が使えるかどうかは処理系定義

規格の観点からは後者の方が正しい
でも、実際問題 FORTRAN と C の相互運用が
できるようにしてあるのが普通。
それ以前にCで読みやすい形にして出すのが普通

char line[MAXLINE];
char *p = line;

while (fgets(line, MAXLINE, fp) != NULL)
{
 p = line;
 while (*p && *p != '\n')
 {
  char num[4 + 1];
  if (!(num[0] = *p++)) break;
  if (!(num[1] = *p++)) break;
  if (!(num[2] = *p++)) break;
  if (!(num[3] = *p++)) break;
  if (!(num[4] = '\0')) break;
  double d = strtod(num, 0);
  printf("%f\n", d);
 }
}
それ以前に喪前のコードは汚い。
改行が(目に見えない)文字コードを持っていて
区切り文字として扱われることはわかってるんだろうか。
何か変なフォーマットだな…。
漏れだったら数字と数字の間には必ず
スペース1個入れると思うぞ。
もしくは、freadで一発で読めるようにするか。
つーか固定長指定フォーマットであることを利用した変換関数を作らない限り
固定長専用の読み込みコードを書く意味はほとんどないんじゃないか?
不正な入力を途中で検出しやすいかというとこの場合はそうはなりそうにないし。
>>519
必ずしもそうはいかないことあるよ実際。
メインフレームのライブラリをナメたらあかん。
FORTRAN だと固定長のやつが簡単に扱えるので
空白を入れないことも多い。
先人の遺したライブラリだと固定長でスペース一個空いてるのでスペースを区切りに使おうとすると、
値が無限大(log(0)計算)のときに指定された幅を*******……で全部埋め尽くされてしまい、あぼーん。

……fortranは嫌いだ
固定長データの読み込みならfscanf使えばいいじゃん。
fstreamにこだわる?
固定長ならistream::read?
istream のメンバ関数を使う場合(グローバルでもあるけど)、
文字列を得る上で終端文字がほしいなら
get, getline系
いらなければ読み取り文字数と戻り値に応じて
read か readsome だな。

fscanf 使えば? ってのは最初のレスにもあるが。
ただ速いけどその分安全性とか拡張性や
エラー処理が不十分だし、一応 C++ のスレってことで
>>529
fscanfの安全性、エラー処理のどこに不満があるの?
必要な機能はそろっているのに。

拡張性がないのは同意しましょう。
>>529

>ただ速いけどその分安全性とか拡張性や
>エラー処理が不十分だし、

危険なコードしか書けないのもエラー処理が十分にできないのも
みんなあなたの技量によるところで、fscanfは無罪。

拡張性については、fscanfそのものを拡張というパラダイムがそもそも間違い。
fscanfを内部で呼び出している拡張版の関数を作るべき。


>一応 C++ のスレってことで

#include <cstdio> // 気は確かか?
また宗教論争が始まりそう。
頭に血が上っているヤツのために断っておくと、別に scanf 系が駄目とか言ってるわけじゃないぞ。
むしろFORTRANとの連携とかローレベルな入力処理にはCの機能の方が適切だとも思ってる。
>>529の発言はそれまでの話の流れで C++ の機能でやるとしたら、
という意味合いを含んでいるんだがわかりにくかったか?
>>532
まぁ、宗教かも知れんな。

俺はバイナリ直で読み書きする場合には fread(), fwrite() で、それ以上のデータ構造を
持たせる場合は boost の正規表現ライブラリ、もしくは lex + yacc にしちゃってる。

動けば何でもよし。
宗教論争とは違うでしょ。
scanf/fscanfが危険だなんていうやつは、ただの無知。
getsが危険なのとは全く違う。
どっちかっつうと可変個引数リストの問題だが
型安全性の欠如はやっぱり問題ないと言い切るのは無理があるんじゃないかと思う。

使用時のミスはプログラマーの責任っちゃそれまでだが、
書式文字列がリテラルじゃないときなんかは特に
「外から」異常状態をチェックして適切な処理を記述するのは困難になる。

たとえば引数中何番目でエラーがおきたかはわかっても、
その型が何であるかという情報すら通常の方法では提供されないわけで。
この辺不完全性を感じなくもない。
そもそも低レベルな入出力ライブラリだし
想定される入力元はほとんどブラックボックスだしで
復帰処理やストリームの状態チェックに関して多くを期待するのは無理な話だとわかっているのだが

文字列としてバッファリングした後に sscanf を使ってファイルの内容を読み込む場合、
ストリームの読み込み位置の情報を受け取っておけば、
復帰処理やエラー出力をするのは比較的やりやすい。
だけど scanf / fscanf の場合、ストリームの読み込み位置を戻せても
それが元と同じ内容を指しているとは限らなかったはず(保証あったらスマン)。

そういう点で、 scanf / fscanf をそのまま使うのは厳しくないのだろうか?
一応質問ってことで「そんなことないぞ阿呆」って言える人は是非後者の場合の対応方法を教えて欲しい。
>>536
入力がテキストの場合だと、ふつー行単位でバッファに読み込んで、その中を
ポインタで動きつつ処理じゃないかね。

iostream が中途半端なのは、しょせん「型」が明確にわかってる場合にしか
使えないし、メンバ中にポインタがからむとアウトという点。いわゆるシリアライズ
処理を実装しようと思ったら、けっきょく ifstream なんか捨て捨てで、自分で
そのあたりの処理を 1 から作る必要がある。
>>537
素朴なつっこみなんだが
型判定部分さえ作ってしまえばそこから先は
IO ストリームライブラリに処理を任せてもしまえばよいのではないか。

高レベルなシリアライズの場合は
むろん型情報を付加してやる際に元のフォーマットに追加しにくいこともあるだろうし、
ネストされたクラスを組み立てていくには境界付けを行うための
特別なフォーマットなんかを用意してやらないと実用に耐えないことになると思うが
>>535
「外から」って?
書式制御文字列をユーザに入力させるってことなら
そういう設計をしたアフォにケリ入れるのが正道だろう。

タコなミスを書いてもコンパイルエラーにならない点は俺も不便を感じているが
そんなのはエラーの中では普通であって幸運ではないだけだ。


>>536
低レベルって?
標準ではPODのみサポートし、それ以外はユーザ定義の関数で対応なら、std::cinも同じこと。
表面的に関数名を同じに見せかけられるか否かの違いでしかない。
テンプレートやマクロを作るときに都合がよかったりはするが、レベルとか言う問題とは違う。

fscanf ・・・ストリーム中のエラー発生箇所がバイト単位でわかる
sscanf ・・・バッファ内のエラー発生箇所はわからない(ポインタを返せない)+バッファサイズが保守しづらい

俺はscanf系の中でsscanfだけはgetsと同格に見ている。
>>536
まあ結局一文字ずつ読んで自前で処理した方が
必要な処理もしやすいし、よけいなことを気にせずに済むかな。

>>539
レスきちんと読んでないのか俺の書き方が不足しているのか、対話が成立していない気がする。

>低レベルって?
続いて復帰処理や状態チェックのための関数が用意されているのかって話出してるじゃない……。

>fscanf
エラー発生箇所を突き止めてその後、
その直前の位置まで復帰させて再読み取りする方法があるかなどについて聞きたいわけ。

ていうか
>バッファ内のエラー発生箇所はわからない
は嘘でしょ。
確かに入力元として渡したポインタが直接動いてくれることはないが、
(その必要もないしときにそれは困ったことを引き起こす)
読み込んだ文字数を得ることは可能。
そもそもそれがわかる前提で>>536のレスを書いてるのは明らかだと思うんだけど。

ただ C-FAQ Chapter-12 と逆の主張が出てる点は興味深いんで、もう少し詳しく説明して欲しい。
>>540
まあ正直言えば、斜め読みっぽいところはある。あくまで2chだからね。
とは言うものの、あなたにここまで言われるほどでもないと思っているぞ。
>レスきちんと読んでないのか俺の書き方が不足しているのか、対話が成立していない気がする。

>続いて復帰処理や状態チェックのための関数が用意されているのかって話出してるじゃない……。
出しかけてはいるようだが、どこがscanf系の論評なのかわからない。
制御情報の一部を隠蔽するのはむしろ高レベルと違うのか?
それとも低レベルとは出来が悪いという意味なら肝心なことを書いていないのと違うか?

>その直前の位置まで復帰させて再読み取りする方法があるかなどについて聞きたいわけ。
最後にungetcして出てきてるやん。

>読み込んだ文字数を得ることは可能。
どうやって?
そもそもパケット破損は検出位置と破損位置がふつう一致しない。
訂正処理はプロトコルの一部として設計すべき。
そこでなぜ通信プロトコル(?)の話が出てくるのかなぞだが。

テキストファイルを扱う場合には、普通は「字句解析」「構文解析」を分離するわけだが
scanf(), istream 系を使うと、簡単なフォーマットなら両方まとめて書ける。ただ、少し
複雑になったり、エラー回復処理を入れようと思うと、両方まとめたことが逆に仇になる。
それだけの話じゃないのか?

俺は、やっつけ仕事を除いては、自前でトークン列まで切り出してから sscanf() で
型変換してる。
544デフォルトの名無しさん:04/01/02 03:34
質問で〜すぅ。うぐぅ。
template<class X>
class C
{
public :
  void operator ()(const X&){}
};

template<>
void C<int*>::operator () (int*const&){cout<<"C<int*>"<<endl;}
これってオーバーロードと解釈?。それとも、テンプレートの特殊化?。
それともうひとつ。
char (6f())[2];のような配列を参照にしてその型をなまであつかえることに気づいた
ひとって日本人?それとも外国人?
だれかおしえてくださいな♥
545デフォルトの名無しさん:04/01/02 03:36
>char (6f())[2];
char (&())[2];まちがえた
複雑なら俺はパーサ作る。
出来合いのパーサ(scanf)で間に合わないときの当たり前の対応だ。

# 542は確かに蛇足
>>544
なぜオーバーロードかも知れないと思ったんだ?

>日本人?それとも外国人?
こいつとhttp://www.cs.bell-labs.com/who/dmr/
こいつ。http://www.research.att.com/~bs/
548544:04/01/02 03:52
>>547
すばやいご回答に感謝。
え〜とですね。
テンプレート特殊化でクラスの再宣言していからそう思った次第です。
それに部分特殊化も出来ないし。

禿さんだったのか。なかなかやるな。
>>543
やっつけじゃない仕事にえらいもん使うんだな(((( ;゚Д゚)))ガクガクブルブル
>>548
もしかして特殊化の使い方がうまくないのか?
template<class X>
class C : public C_base<X>
{
public :
};
としておいて二度手間にしたくない部分をC_baseに詰め込むなんて手もあるが。
551544:04/01/02 04:28
>>550
えーとですね。
せっかく答えていただいてなんですが。
テンブレートに関してはMC++Dとか読んでかなり勉強したんですよね。
でもつい先日>>544のようなコードを見掛けたのですよ。
そして、えっ。これって、コンパイルされるの?
だって、特殊化のためのクラス宣言がないよ。て、感じて、コンパイルしてみたらあっさり通るじゃないですか。
「ありゃ」、「ありゃりゃ」。どうなってるの?てな訳で今に云ったってるわけなんですよ。


テンブレートは習ったことないんでよくわかんないや。
554544:04/01/02 05:22
>>552
ごめんなさい。英語読めないんです。
やっぱ、洋書ぐらい読めないときついか。
555 :04/01/02 05:44
Kさん 好循環  Aさん 悪循環  
 (健康体)  (喘息)

1.(神が喘息であるかないかを決める)
2.K 喘息でない人 A 喘息の人は
は体力がある    体力がなくなる

3.K        A 行動力、
          五感(嗅覚)が鈍り感性が変化する

4.K&A 神は異常な感性の人間は本来人に迷惑をかけ
るから外に出てはいけないと思っている。

5.K 変化なし   A アトピーになる
6.K 正常な感性  A 外に出なくなりさらに異常な感性になる
7.K 正常な人間   A 異常な人間(レッテル)
8.K&A 死  9.K&A      来世
10.K&A 神は異常な人間は人に迷惑をかけるので行動
を抑制する必要があると思っている。

11.K&A 神が喘息であるかないかを決める
12.K 喘息でない  A 喘息である
13.K&A    1.に戻る

これは事実。広めようぜ
解決法:寝て起きて、やな気分でも、続けるけること。
体力をつけると感覚が正常に戻り、
アトピーも快癒に向かう。 目安としてグランドを10週くらい。
あとはウォーキング 2.3時間を目安にウインドーショッピングや本屋めぐり
最近、変質者が小学生を襲ったりする事件が頻発してるのはお前が
そんな電波だしてるせいで変質者が外出するようになったからか。

>>555 は氏ぬべきである。しかもただ氏んで終わるものでは(以下略
>>554
552が貼ったリンクをよく嫁
JIS規格、つまり日本語版があるって書いてあるやん
>>557
JISのは英語だよ、邦訳は出てない。
559540:04/01/02 12:43
今更長レスするのも何だけど
>>541
低レベルという呼称に良否を下されたと思って腹を立てている? なら誤解だ。
抽象度の高くモデル化されたファイル入力をかなり直接的に扱う stdio と
例外機構や多数の関数群などの提供する機能の豊富さ/肥大さを持った iostream の性質の違いを指してる。
iostream ファミリのエラー処理機構が scanf 系に比べ
それほど満足できるもんじゃないと言うのなら、確かにそうだ。

で、ungetc が fscanf に対しても使えるとは知らなかった。
(むしろ内部バッファの処理と衝突しそうな気もするんだけど……)
が、それが出来ても「読み出したものを戻す」戦略が「貯えたバッファ内をランダムアクセスする」戦略に対して
殊エラーからの復帰処理に関して同程度に置けるものとはやはり到底思えない。

読み込んだ文字数を得るには "%n" を指定する。
つかこれできないとエラー復帰処理以前に
一つのストリームから段階分けて読み込むことすらできないあり得ない関数になってしまう。
>>558
まぢっすか?
買わなくてよかった
561デフォルトの名無しさん:04/01/02 22:29
『標準入力からテキストファイルを読み込み、単語を検出して辞書順に並べ、出現頻度を標準出力に出力しなさい。』
って宿題があるのですが分かる方お願いします。オートマトンとかそういうのを使っていたと思うのですが・・・ 
単語の定義と辞書順の定義をまずはっきりと規定しなさい
>>561
宿題スレへどうぞ。

ぼるじょあがC/C++の宿題を片づけますYO! 18代目
http://pc2.2ch.net/test/read.cgi/tech/1071407728/
海外掲示板用オフラインリーダーを作るスレ
http://pc2.2ch.net/test/read.cgi/tech/1072883528/

海外でよく使われていうる掲示板スクリプト
専用のオフラインリーダー作って下さい。

必要な条件はID、PASSを管理できること、
OpenJaneみたいな三面型の見た目。
簡単にローカライズできるように言語ファイルを採用
565デフォルトの名無しさん:04/01/03 07:04
%5d、%-8d、%7.2f など Cでの数値の書式制御を
C++記述で表現する方法ってあるんでしょうか?

例)
int a=123;
printf("%5d", a);
実行結果 __123



int a=123;
cout << ?????
setw
ios
>>565
一通りある。まあ >>566 で十分わかるべきだが例:
cout << setw(5) << a;
568565:04/01/03 07:30
>>566-567
ありがとうございました。。<(_ _)>
boost::formatという手もある
>>569
>565にはまだ早いような。
だって、operator << のオーバーロードが働いてる事も知らないよ。
早いとかそういう問題じゃないだろ。
元の質問は明らかに標準のIOストリームライブラリについてのものなんだから。
使えるヤツには format の方がずっと使いやすいが初心者にまで見境なく勧める方が間違い。
>>559
そんなもん使ったところでバッファサイズを決めうちしてる時点で(ry
・・・と言いたいところだが、%nには思い至っていなかった。
なので、ここで恥の上塗り的な即レスは悪いが中止するんであしからず。
また機会あったら議論しようぜ。
C/C++相談室で放置されたので、こちらで質問させて下さい。
複数の引数を持つコンストラクタを使ったオブジェクト配列は作れるのでしょうか?
例えば私の知識では
myclass ob[3] = {myclass(1,1), myclass(1,1), myclass(1,1)};
とする方法しか存じておりませんが、この方法は
1) 各obに同じ引数を渡したいのに、各々引数を明示するのがバカっぽい
2) こんなことができるのはせいぜい数個の配列まで
の2点から、とても実用できるシロモノではありません。
そこで、こういったケースでは何を行うか、先輩方の御知恵を仰ぎたいのです。
よろしくお願い致します

// gcc 3.3.2 では ob[3] = myclass(1,1);でできちゃったけど、これは拡張機能?
>>573
std::vector< myclass > ob( 3 , myclass( 1 , 1 ) );
>>573
配列の要素となるオブジェクトは可能ならデフォルトコンストラクタ(と代入演算子)を用意する。
初期化子が途中で省略できないし、new[]もできないなどといろいろ困るので。

生成後に代入する手間はこの場合は気にしてはいけない。
どうしてもデフォルトコンストラクタが呼べない場合は、ポインタの配列を作って
1個1個 new するなり、他で作ったオブジェクトへのポインタを渡してやるなどするのが常道。
(たとえばすべての要素が同じ値を持っていて変更されないなら後者もアリ)

>>574
それデフォルトコンストラクタ呼んだ後でコピーしてるぞ。
(つーかSTLコンテナの要素はDefaultConstructableかつAssignableという要請がある)
576574:04/01/04 06:09
>>575
どこでデフォルトコンストラクタが呼ばれるの?
>>576
myclass の new[] を行うときに。
578574:04/01/04 06:34
>>577
してねーよ。
コピーコンストラクタしか使ってない。
STLの中にデフォルトコンストラクタを要求する操作があるが、
std::vectorのコンストラクタはそうでなかったような気が。

std::vectorのコンストラクタは無属性のメモリを予約サイズ分確保して、
必要な個数分、placemant new を使って初期化を行う。
初期化パラメータつきのstd::vectorのコンストラクタは
引数つきのplacement newを使用するんで、この場合デフォルトコンストラクタは
呼び出されないはず。

デフォルトコンストラクタが要求されるのは、例えば std::mapの operator [] とか
じゃないかな。
>>575
> STLコンテナの要素はDefaultConstructableかつAssignableという要請がある
これは間違いだな。

23.1 -3-
The type of objects stored in these components must meet the requirements of CopyConstructible types, and the additional requirements of Assignable types.
581575:04/01/04 07:01
ああそうか。
コピーは確かに必要だが、
メモリ確保しておくだけでいいからデフォルトコンストラクタが呼ばれる必要はないか。
すまん早とちりだ。>>574
STLのコンテナはって言い方は確かに一般化のしすぎだったが
resize とかがあるから vector にはデフォルトコンストラクタは必要では?
#クラステンプレートだから使わない限り怒られないと思うけど。
>>582
ob.resize( x , myclass( 1 , 1 ) );
もうちょっとちゃんと調べてからものを言ったほうがいいと思います。
>>583
resize(size_type n , T t = T() ) だろ。

Sequence と Associative Container はやっぱり DefaultConstructible だ。
( list が Reversible Container で違うんだな)
>>584
「使わない限り怒られない」から「デフォルトコンストラクタは必要」ではないです。

> Sequence と Associative Container はやっぱり DefaultConstructible だ。
> ( list が Reversible Container で違うんだな)

Sequence と Associative Container はたしかに DefaultConstructible ですが、
要素の型は DefaultConstructible である必要は無いはずです。
あやしいので情報元を示してください。
要素の型と勘違いしてた。OTL
type に対して要求されてないと駄目なのね。
指摘ありがとう。
年賀状は、謹賀、賀正などの「賀詞」、
新年おめでとうございます、などの「祝詞」で始まります。
「賀詞」の場合、“賀正”、“迎春”、“賀春”は、
目上の人に対して失礼な言葉なるので注意しましょう。
目上の人に対しては「祝詞」を使った方が無難です。
>>587 へぇ〜 へぇ〜 へぇ〜 へぇ〜 へぇ〜
でも多分目上の人もそう書かれて失礼だとは思わないよね。
出力を.txt形式のものにしたいのですが,どうしたらよいでしょうか.
リダイレクト
fprintf
Borland C++builder いがいに使いやすくて便利なものあれば教えてください
Visual C++
Javaが動く環境ならEclipse+適当な言語
595デフォルトの名無しさん:04/01/06 00:26
ダイアログベースで簡単なプログラムを作りたいのですが
その中のいくつかの関数は int ,CString 型の変換ややり取りしかしません
それをコンソールでテストしながら作りたいのですが

CStringを使うときに必要なヘッダーを教えてください。

自分の力では検索で見つけられなかったのでお願いします
596デフォルトの名無しさん:04/01/06 00:28

コンソールで→Win32 Console Applicationで
>>595
スレ違い。VC++スレにでも行って聞け。
598デフォルトの名無しさん:04/01/06 01:34
わかりました
どうも
>>589

そもそもよまな(ry
600512:04/01/06 07:38
>>512-513 の件、
皆さん、有り難うございました。

結局、 fscanf() で記述しました。
吐き出しは、boost::format() で。
>>516氏や>>519氏に似たコードです。

以前作成したときは、低レベル関数を使わないで、
と思ったので、getline()で読み込んだ後(>>529氏のレス参照)、
substr()で切り出したり、
特殊な場合('.'の位置によって区切り位置が変わってしまうときがある)は、
boost::tokenizerなどを駆使して、やっていたのですが、
FORTRANの場合、大人しくCの機能を使った方がよいようですね。

ちなみに、FORTRANはg77@Cygwinを、
C++はVC++7.1を使っているため、
>>515氏の方法は取っていません。
601512:04/01/06 07:41
にしても、FORTRANをC++に移行する需要って
結構あると思うんですが、
そういったライブラリって、意外にないものなんですね。
(f2cだと入出力の部分は独自になってしまうし)

いろいろと勉強になりました。
>>601
Intel(R) Visual Fortran と Visual C++ との連携がいいのでは?
http://www.xlsoft.com/jp/products/intel/compilers/iftnwin.html
6万円以上するから無理には薦めないけど。
そういや、>>515 で、
test 呼ぶときにも FNAME 使うのを忘れてたな。
for(i=0;i<1000;i++){
cout << i << "," << a[i] << endl;
}

みたいなプログラムがあったとして、実行結果が1000行になってしまうので
DOS窓では見られません。(WinMeです)
テキストにするにはどうしたらよいでしょうか。
リダイレクト
>>604 リダイレクト
リダイレクト > リダイレクト
>>604
c:\hoge > output.txt

これでoutput.txtに出力される。
>>605-607
ワラタ

>>604
608のような方法で
コマンドの標準出力を
テキストファイルに出力することを
リダイレクト、っていう。
C:\> hoge | more
>>610
パイプ
vector<string>のなかからstring::empty()==TRUEのものを削除したくて
以下のようにしましたが、エラーが出ます

s.erase(
  std::remove_if(s.begin(),
     s.end(),
     std::mem_fun_ref(&std::string::empty)),
  s.end);

c:\my documents\my project\vc\mysources\dnabbandex\commonaccess.cpp(221) : error C2664: 'mem_fun_ref' :
1 番目の引数を 'bool (__thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::*' から。。。

どのようにすればいいのでしょうか?
お願いします。

>>612
最後の s.end を s.end() にしてもダメ?
>>612
VC6だよね?const_mem_fun_ref_t とかが用意されてないので
const メンバ関数に mem_fun は使えなかった記憶がある。
VC.NET 2003 なら通ったっす。
615612:04/01/06 22:33
>613,614
ありがとうございます。

おっしゃるようにVC6の問題のようです。gccでもとおりました。
型Tについて、例外値を持たせたい。
ポインタで言うところのヌルポインタのように。

template<typename T>
class Holder {
 public:
  Holder(T v) : _valid(true), _v(v) {}
  Holder() : _valid(false) {}

  bool isValid() const {return _valid};
  T &getValue() const
  {
   if (!_valid) throw 例外;
   return _v;
  }

 private:
  bool _valid;
  T _v;
};

他にいい方法ありますでしょうか?
617sune:04/01/08 23:32
スマートポインタにして例外はヌるポで代用
618デフォルトの名無しさん:04/01/08 23:42
依存関係にある型限定子とはどのようなものを指すのでしょうか?
教えてください
>>616
boost::optional。いや、やってることは本質的にキミのコードとあまり変わらんけど。
>>616
ポリシークラスで、例外値を定義する。
621デフォルトの名無しさん:04/01/09 01:10
基本クラスでデストラクタを、virtual指定すると、
その派生クラスのデストラクタはすべて仮想関数になるんですか?
はい
>>621
単一継承する限りはな。
624デフォルトの名無しさん:04/01/09 02:04
inline関数にするのとしないのではどうちがうのですか?
ヘルプを読んでもよくわからないのでinlineって使ったことないんですけど
なんかまったく困らないのでどうでもいいのでしょうか?
>>624
一般的にはどうでもよくないけど、
君にとってはどうでもいいよ。
C では単純な処理の場合、呼び出し時間が無駄だからって
関数の代わりにマクロという厄介なものを使うことがあったけど、
C++ ではそれを回避するために inline 関数が導入されたんだよ。
627デフォルトの名無しさん:04/01/09 03:18
gcc だったら -O3 option をつければ inline とほぼ同じになるんだっけ?
628616:04/01/09 03:38
>>617-620
ありがとうございます。
あながち的はずれなコードではないことが判っただけでも安心しました。
>627
実装が翻訳単位にあればそうかもしれないけど
(ヘッダファイルとかさ)
なければ普通は最適化オプション程度でのinline化は無理では。

UNIX(LINUX)で、永久ループをする常駐物を作っています。

clockで時間を計測して正確に200ms毎に実行したいのですが、
どうすれば良いのでしょうか?

sleep()は1秒単位ですし、selectをつかうとすぐに結果が返ってきてしまいます。
ms単位のsleepって無いんでしょうか?
書き忘れました。
からループとかを使えばすぐにできるのですが、
マシンパワーを使わないようにするためにsleep等を使いたいのです。


具体的な処理内容は、socket接続の待機と、socketの受信データによる挙動です。

>>630
nanosleep(2), usleep(3)
>>631
でもsocketの待機になんでsleep+ポーリングなんかするんだ?
よっぽど大量のソケット回すのか
634633:04/01/09 09:55
書き忘れたけど、スレッド分けてブロックする手をなぜ使わないのかってことね
>632
投稿した直後、さらにぐぐってusleep()を発見しました。
でもありがとう。

はじめにぐぐったら、
sleepは1秒単位なので、ms単位の待機ならselectを使え!みたいなWebがあったので、
変なハマりかたをしてしまった。

>633

秒間x回、
1、ゲームサーバーとしての挙動(物理演算とか)
2、新規接続の確認
3、clientからのデータの処理

同人ゲーム作ってるってかくの、なんか気が引けました。
ここから1を抜いたので変な質問になりました、すみません。

ていうかC++の質問になってませんよ
637デフォルトの名無しさん:04/01/09 14:57
BlitzやMTLなどのライブラリを使いたいんですけど
どこかに日本語による詳しい解説でもないでしょうか。
638sage:04/01/09 17:05
いい機会だから英語を覚えなさい
639デフォルトの名無しさん:04/01/09 18:46
bccでコンパイルしたプログラムのファイルサイズを46kbぐらいより小さくする方法ってありますか?
UPXを試してみたけどエラーで起動しなくなるし...。
640sage:04/01/09 19:17
スタートアップコードを自前で用意しなさい
>>639
環境によるだろ。
俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力
ランタイムを使用するようにして使っているが、例えばstd::vectorを
使っても使わない時と比べ10Kほどしか増えない。
>>641
>環境によるだろ。
タワラ
>>641
某スレで見た覚えのあるレスだな
コピペか?
>>641
すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。
懐かしいなぁ、もう。
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。
とかいうエラーが出るんだけどこれってどうすればいいの?
>>646
#include <stdafx.h>

後死ね。
>>647
言葉が悪いな。それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。
649639:04/01/10 09:10
>>640
スタートアップコードって?という状態だから諦めろ、ってことなんだろうな…。
bccの中の人がでっかい張りぼてを用意した所為、って理解で良い?
>>647
#include "stdafx.h"
>>639
エクストリームな小ささを求める場面(実際ある)はアセンブラの出番
リンカの定義ファイルも自分で書いて細部にわたって贅肉を落とすべし

スレ違いすまそ
土日、祝日になるとただでさえ少ないレスが0になるよね・・・。
>>651
TClockの作者さんがNASMでスタートアップルーチンを指定する方法を解説していたのを思い出して
読んでみた、が、やはりちんぷんかんぷん…。

実行ファイルのサイズを小さくする
ttp://homepage1.nifty.com/kazubon/progdoc/tclock/nodeflib.html
>>652
なんか最近さびれちゃったね。
それとは対照的になんか cppll が最近活発になってるし、
ここの住人がアッチへ逝っちゃったのかのなぁ?
>>654
最近cppllの話題の質が下がってきたと思っていたが、
そういう事だったか・・・・
じゃあ俺もあっちに参加できるかな
>>657
cppllの質の低下を危惧した某氏が隔離MLとして作ったと
思わるる。
次のような定義だったら…

class TYPEA{
〜〜
};
class TYPEB:public TYPEA{
〜〜〜
};

TYPEB varB;
//------------------------------

(1)varBがTYPEBのインスタンスである事を調べる関数はありますか?
(1)varBがTYPEAから派生した型のインスタンスである事を調べる関数はありますか?
>>659
関数オーバーロードやテンプレート引数のマッチングルールを利用するテクニックはあるが
>>659
何らかのフレームワークに沿って実装するか、処理系依存の機能を利用しない限り、
C++の言語仕様のみでは無理かと。
dynamic_castは?
>>659
typeid(varB) == typeid(TYPEB)
dynamic_cast<TYPEA*>(&varB) != NULL

ただしTYPEAやらTYPEBやらに仮想関数が存在することが前提。
>>661
>C++の言語仕様のみでは無理かと。

RTTIについては662,663に先に言われてしまったが
仮にそれを知らなかったにしても
せめてこのくらい思いつけよ

class TYPEA {
//...
virtual const char* kind() const;
};
// ...
const char* TYPEA::kind() const { return "TYPEA"; }
const char* TYPEB::kind() const { return "TYPEB"; }
>>664
>>661
> 何らかのフレームワークに沿って実装するか、
型情報が失われたポインタですら簡単に判定できる

class TYPEA {
private:
static std::list<const void*> objects;
public:
TYPEA(); // register
~TYPEA(); // unregister
static bool isTYPEA(const void*); // search
};

処理系に依存しない「C++の言語仕様のみ」でどうにでもなるyo
多重継承にはpairが要りそう
typeidは標準だけどな
>>666
>>661
> 何らかのフレームワークに沿って実装するか、
ところで共通の配列に属さないポインタを比較しても良いの?
>>670
大小関係は意味ないが、一致・不一致判別にはよく使う
> 一致・不一致判別にはよく使う
その結果を仕様として定義されているのは NULL との比較だけだったと思ったが。
たとえば Intel 8086 用のコンパイラにおける far pointer 同士の比較が相当する。
>>670
規格上は、良くない。less<T*>::operator() を使う。
>>672
8086でのfar pointerのように同一アドレスを表す表現が沢山あるものは
正規化しない限り同一性の比較も正しくできなかったな。

でも、規格(ISO 14882-1998)では...
5.10 - Equality operators [expr.eq]の-1-
>...Pointers to objects or functions of the same type (after pointer
>conversions) can be compared for equality. Two pointers of the
>same type compare equal if and only if they are both null, both
>point to the same object or function, or both point one past the
>end of the same array.
うーん、この文の中では同一オブジェクトへのポインタ同士はequalだと
書かれているが・・。
>>672
5.10 Equality operators の 1
> Pointers to objects or functions of
> the same type (after pointer conversions) can be compared for equality. Two pointers of the same type
> compare equal if and only if they are both null, both point to the same object or function, or both point one
> past the end of the same array.
比較演算に関しては確かに不定と書いてあるんだが、==, != に関しては問題なさげ。

あと現実問題としてリニアなメモリモデルが主流になっているから、よほど特殊な
環境に移植するのでなければ、その辺は気にしなくて良いと思われ。far ポインタ
とか言いだした段階で既に処理系依存の拡張機能だしさ。
>>673
詳細きぼん
>>676
違うオブジェクト/配列を指すポインタ同士の大小比較は
実装はともかく規格上では unspecified なのだが、
less とか greater とかのテンプレート だと、20.3.3 Comparisons:
> 8 For templates greater, less, greater_equal, and less_equal, the spe-
> cializations for any pointer type yield a total order, even if the
> built-in operators <, >, <=, >= do not.
正しく全順序がつく( (p<q && q<r) == true なら (p<r) == true になる、etc... )
ことが定められている。っちうこと。
>>677
比較の最中に大小順が逆転しないことが保証されてるってことか?
だったらlessでも<でも同じで>>670に対して何が言いたかったのか
やっぱりわからん
>>678
< では保証されてない。less では保証されている。
680679:04/01/11 22:26
あー、何で混乱させてしまったのかがわかった。書きたかったのは
> 正しく全順序がつく( (p<q && q<r) == true なら (p<r) == true になる、etc... )
じゃなくて
> (less<T*>()(p,q) && less<T*>()(q,r)) == true なら less<T*>()(p,r) == true
だ。スンマソン.
>>679
未規定な大小順が逆転しないことの保証に何の意味がある?
まさか等値非等値が逆転しないことと混同してないよな。
>>670に対して何が言いたかったのかやっぱりわからん
StrictWeakOrdering?
>>659
(1)まあ663のようにRTTIを使うという手もあるけど、これだと仮想関数とRTTIなしで実現できる。まあ必要性薄いけど。

template <typename T>
struct IsTYPEBImpl{
    enum{value=0};
};
template <>
struct IsTYPEBImpl<TYPEB>{
    enum{value=1};
};
template <typename T>
bool IsTYPEB(const T & arg){
    return IsTYPEBImpl<T>::value!=0;
};

(2)はLokiのSUPERSUBCLASSやboostのtype_traitsのis_base_and_derivedあたりが使えるかな、ただしコンパイラ選ぶけど。
685684:04/01/12 04:56
追記
参照とポインターの参照先については正しく動かないので注意が必要。
そういう場合は素直にRTTI使った方が吉。
template関数の引数の型調べたりとかには使えるけど。
686デフォルトの名無しさん:04/01/12 05:32
いきなりレベルが低くなってすまんのだがCだと
fp = fopen(file, mode == read? "rb": "wb");
という感じで簡単に読み込み方法をasciiとbinaryを書き換えられるんだけど
これをC++風にするとどうなるの?
>>686
それはバイナリモードか否かでなくて、読み込み用か書き込み用かを切り替えてると思うが。
その後の操作考えると壮絶に意味がないんじゃないか?

それはさておきC++なら
std::ifstream hoge(filename, is_binary ? std::ios_base::binary : 0):
688686:04/01/12 05:50
>>687
質問の意味すら違ってくる致命的ミスなのに優しくフォローありがd。
689679:04/01/12 08:36
>>681
その保証があるおかげで、例えば std::set<T*> や std::map<T*> が
正しく動作することが保証される。物凄く意味のある保証ではなかろうか。

>>682
> ところで共通の配列に属さないポインタを比較しても良いの?
に対して、「< が < っぽく振る舞うことを期待するなら、異なる配列に
属するポインタを < で比較しちゃいけない」と言いたかっただけなんだが。

比較は比較でも等値比較 ==, != は問題ないってのは他の皆さんが書いたとおりだし、
最悪、例えば共通の配列に属さない配列を比較したら常にtrueが返るという
実装でもいいなら、 <, >, <=, >= で比較してももちろん構わない。

# 何回も書いてるように、<,>,<=,>= がうまく機能しないような実装は、
# "現実には"ほぼ存在しないと思って問題ないだろうけどね。
×共通の配列に属さない配列
○共通の配列に属さないポインタ
(1) T hoge = 0; と
(2) T hoge = T(0); って

T hoge(0); と同義になるんじゃなかったでしたっけ?
(2)の書き方するとコピーコンストラクタが呼ばれちゃうんですけど
>>691
(3) T hoge(0);
(1)と(3)が同じなだけかと
>>692
(1)もコピーコンストラクタ呼ぶです(mingw)。
こっちでは普通のコンストラクタが呼ばれるがなぁ。 > MinGW
#include <iostream>
using namespace std;

class A {
public:
 A() { cout << "A" << endl; }
 A(int a) { cout << "int " << a << endl; }
 A(const A& a) { cout << "Copy" << endl; }
};

int main() {
 A a = 0;
}

出力 (MinGW's g++ 3.2)
int 0

出力 (Cygwin's g++ 3.2)
int 0

出力 (VC++ 7.0.9486)
int 0
>>694
コピコンよばれちゃいます。
コンパイル通りません。
template
<
 typename T,
 typename SrcPointerType = T*
>
class CMustAssignedPointer
{
 private: typedef CMustAssignedPointer ThisType;
 private: SrcPointerType m_SrcPointer;
 private: CMustAssignedPointer();
 public: CMustAssignedPointer(const ThisType& rhs)
  : m_SrcPointer(rhs.m_SrcPointer)
 {
 }
 public: CMustAssignedPointer(SrcPointerType rhs)
  : m_SrcPointer(rhs)
 {
 }
};

int main()
{
 int* p = NULL;
 std::auto_ptr<int> p2(new int(100));

 CMustAssignedPointer<int> pNum = p;
 CMustAssignedPointer<int, std::auto_ptr<int> > pNum2 = p2;
}
コピコンが呼ばれてコンパイルが通らない理由は
std::auto_ptrのコピコンが非constのrhsを要求するからだというのは
わかってるんですが…
CMustAssignedPointer(SrcPointerType rhs)
でそれを回避したいのです。
>>689
setやmapで必要になるのは等値非等値か指し示す先の比較やん。
670に対して何を言おうとしたのかはなんとなく見えてきたが到底賛同できるものではないな。
たとえばintを戻す関数ポインタを引数に取る関数があるとします。
void foo(int funcptr());
普通の関数int bar() {return 0;}の場合は、foo(bar)で関数ポインタを渡せます。
ここにメンバ関数の関数ポインタを渡すことはできるのでしょうか?
class Foo {
public:
 int bar() {return 0;}
};
のクラスの場合、fooに渡す引数にはどう書けばよいのでしょうか?
700699:04/01/12 13:00
すみません、ちょっと追加。
int main()
{
 Foo* f = new Foo();
 foo(??);
}
のときの"??"の部分にどう書くかという質問です。
>>699
なにをどうやっても非staticなメンバ関数を通常の関数ポインタに渡すのは不可能。
>>699
そのままでは無理です。メンバ関数ポインタは普通のポインタとは区別されます。
解決策1:fooを多重定義orテンプレート化(fooを変更できて、且つfooが複数になってもかまわない場合)
    void foo(int (Foo::*fun)());
    template <typename Fun>
    void foo(Fun fun);
2:汎用のファンクタを利用する(fooを変更できる場合)
    void foo(boost::function<int ()> fun);
3:Foo::barをstaticにする(barがFooの非staticメンバにアクセスしない場合)
4:Fooのインスタンスを名前空間レベルで保持する(最後の手段)
    Foo f;
    int foo_bar() {return f.bar();}
この場合、foo_barをfについてテンプレート化することで、冗長なコードを記述しないで済ませられます。
703699:04/01/12 14:11
>>701-702
早速の回答、ありがとうございました。
staticにすればfoo()に渡せるのは解っていたのですが、Foo::bar()内でメンバ変数(インスタンス変数)に
アクセスしたかったのです。
foo()というのは、callbackの登録をするための関数で、提供されたライブラリ内にあり変更できません。

正直>>702の内容は、3を除いてあまりよく理解できないのですが「非スタティックなメンバ関数を
通常の関数ポインタに渡すのは不可能」ということがわかっただけでも大きな収穫です。
今までどうにかしてキャストしようとして悪戦苦闘していたもので・・・。

702さんの情報をもとに、さらなる勉強をしようと思います。
ありがとうございました。
704699:04/01/12 14:14
多分僕にはvtptrなどのC++のメカニズムに関する知識が欠けているので、このような問題に
対応できないのだということを思い知らされました。
705699:04/01/12 14:19
あぁぁ、すみません。独り言を書き込もうとして、途中でやはりやめようとしたんですが、
間違って書き込みしてしまいました。
スレを汚してすみませんでした。
>>704
一応解説してみたり。
非staticなメンバ関数を呼ぶには
関数のアドレスだけでなく、(thisになる)オブジェクトのアドレスもまた必要。
この二つが揃って初めて呼び出しが許される。

で、メンバ関数ポインタ型としてメンバ関数のアドレスを単独で取り出した場合
"->*"や".*"演算子でオブジェクトとくっつけない限り呼び出せない。

ただ、間接的に扱うときにこの二つのデータをバラバラに扱うのは面倒なので、
ひとつにまとめて運ぶ手段としてよく使われるのが関数オブジェクト(ファンクタ)。
食生活で顎の発達が阻害されて歯の生える場所がないからだが、
場所自体が無いのに矯正だけで直るものなの?
やっぱり場所確保のために歯を何本か抜いちゃうの?
>>704
推薦図書

ISBN4-8101-8101-4
void foo(int callback(void*), void* data);
みたいになってれば間接的にメンバ関数呼べるんだがな。
710699:04/01/12 15:06
うぅぅ、皆さんどうもありがとうございます。
2chでこんな優しい人たちに会ったの初めてです(感涙

>>708 早速今から秋葉の書泉に買いに行ってきます。

>>709
なってます。後出しの情報ですみません。
ライブラリは一度クライアントコードの
void baz(void** buf, size_t size, void** handle)
というのを呼び出します。bazでは
baz(void** buf, void* handle)
{
 *buf = new unsigned char[size];
*handle = 任意のポインタ
}
とかできます。そのbufにライブラリは値を設定して、handleとともにコールバックしてきます。
このvoid baz()はstaticで全然かまわないんですが、bazの中でnew Foo()したかったんです。

と、ここまで書いて、callbackの設定はbazの外側でやるのだから、new Foo()したポインタは
使えないということですよね。なんか、混乱しまくってます。
もうちょっと自分でよく考えて見ます。
連続書き込みですみません。
fooとかbarとか使うから良くわからない書き込みになってるんですよね。
これらの仕様書は会社にあって今手元に無いので、明日会社に行って、
いろいろ試してから、再度質問する場合は、それらしい名前に変えて書き込みます。
(できる限り自己解決するつもりです)
712デフォルトの名無しさん:04/01/12 15:21
柴田望洋著の「C++プログラミング言語」の演習問題解答のソースプログラム持っている人いませんか?
listのソースは後援ページからダウンロードできるんですが、演習問題の解答がなくて困っています。
「例解演習」の方も買いましたが、微妙に違うところがあります。
学校で習っているのですが、提出期限に間に合わなくて。。。。
知っている方教えてください。
class Foo
{
public:
 static int callback(void* ptr)
 {
  return reinterpret_cast<Foo*>(ptr)->finc();
 }
 int func();
};

Foo* obj = new Foo;
foo(Foo::callback, reinterpret_cast<void*>(obj));

C++でコールバック関数使うときの定番。まぁ、callbackは独立した関数でもいいんだが。
>>698
> setやmapで必要になるのは等値非等値か指し示す先の比較やん。

「等値非等値か指し示す先の比較」ってなに?
==,!= のこと?
#include <stdio.h>
void main()
{
  printf ("\t\b\b");
}

w2kでこれやると落ちると聞いたんですが本当ですか?環境がなくて試せませぬ
>>715
スレ違い

そんなカビの生えたコードを今頃見つけて喜んでる知障は氏ね
C++(iostream)でfseekにあたるのは何ざましょ?
>>714
たぶん、

 set<int*>

と使うにせよ「ポインタ値の代償ではなく、実際の int 値の代償でソートするように
関数オブジェクトつくって渡すのがふつーだろ」と言いたいんじゃないの?

ポインタ値でソートしたいこともあるけどなぁ。生ポインタをそのまま使わず、Windows
の HANDLE みたいにラップした値を返して使うようなフレームワークを作るときに、
HANDLE <-> 生ポインタ相互変換部分を map で書くとかさ。
719679:04/01/12 16:57
>>698
> setやmapで必要になるのは等値非等値か
ワシは等値非等値って == と != の結果のことだと理解していたんだが、
setやmapにそれは必要ない。どういう意味でその用語を使ってるか
説明してくれると嬉しい。
> 指し示す先の比較やん。
set<T> でなくて set<T*> よ?指し示す先を比較してどうする?
>>717
seekgとseekp
こんな風になるかなぁ
#include <iostream>
class Foo
{
public:
void foo(){ std::cout << "Foo::foo" << std::endl; }
};
void func(void (Foo::*memFunPtr)(), Foo &f)
{
(f.*memFunPtr)();
}
int main()
{
Foo f;
func(Foo::foo, f);
return 0;
}
>>719
equality と equivalent の訳語の話か? それだと人によって用語がマチマチだから、
C++ の規格書通りの英単語を使った方が良いかもしれん。
もうその話題はいいって
724アルティメット ◆17Hz8gAKSA :04/01/12 20:42
初めまして皆さん
自分は専門学校の情報処理科2年制に勤めているアルティメットと言います
実はかれこれ1年近くいるくせにC言語プログラミングを全く理解していません
何度か真面目に理解しようとしたのですがちっともわかりません
最後の手段として2chに頼ろうと思います
皆さんよろしくお願いします
カエレ
>>724
嫌です。すぐに進路を変更して下さい。
>>724
いろんな意味でスレ違い
いえいえ
頑張って理解しようと思うので
どうか大目に見てやってください
頼みます
>>724
2chに頼ることの是非はともかくとして、お前は何をして欲しいんだ?
カエレッツッテンダロ
ワラタ
そうですねぇ
C++で出来る範囲の問題を出してみてくれます?
なんとか解いてみせますので
とりあえず今わかるのが
printf 文字列表示
int 整数定義
char 文字数定義
float 浮動小数点数定義
%d 整数表示
%f 小数表示

このぐらいなんですよ
学習1日目か。先は長いぞ。
とりあえず入門書1冊とK&R読み終えてからまた来い。
ここはC++なのでK&R読んだからって来られても迷惑なんだが。
C++3rdならともかく。
>>719
おまえもひつこいな
set<T*>での同一配列に属さないオブジェクトへのポインタの等値非等値でない大小比較に何の意味がある?
意味があるかどうかではなくコンパイル通ったってだけな議論ならそろそろ見限るぞ
>>737
> set<T*>での同一配列に属さないオブジェクトへのポインタの等値非等値でない大小比較に何の意味がある?
上で誰か書いて他が、ポインタを生で見せるのは嫌だから汎用のハンドルクラスを
作りたいとか。クライアントには THandle だけ見せて、T* は一切見せないようにする。
Windows の HWND とかUNIX のファイルデスクリプタなんかと同じように。

STL で書くと、こんな感じになると思うが。

template <class T, class THandle>
class HandleManager {
public:
  T* getPtr(THandle h);
  THandle register(T* p);
  void remove(T* p);
private:
  std::map<T*, THandle> p2h;
  std::map<THandle, T*> h2p;
};

まぁ、俺なら STLport 入れて hash_map 使うけど。
>>737
719ではないが、
大小比較ができなければ、そもそも set<T*> を作れない。
ポインタに対して大小比較ができること(less<T*>が定義されていること)が本質的。

たとえば、
typedef void* HWND;
のような定義がされている場合に、
set<HWND>を実現するためには less<HWND>が定義されていなければならない。
すなわち less<void*>が安定して計算できる必要がある。
741679:04/01/12 23:39
>>737
だから説明してあげるから、その"等値"という用語の、キミの使っている
定義を教えて下され。申し訳ないが、「等値非等値でない大小比較」の意味が
ワシには理解できてないので、それに何の意味があるのかは説明できない。

一応とこっちの主張をまとめさせてもらうと、
ワシのしたい主張は 「less<T*>() を使った比較なら、同一配列に属さない
ポインタも含めて全順序(total order)になることが保証されている。」 だけだ。それに
> 何の意味がある?
と問われれば、何回か書いたように、「この保証のおかげで、set<T*> や
map<T*> に同一配列に属さないポインタを放り込んでも正しく動作する
ことが保証されるので、嬉しい」という意味がある。もっと具体的に書いた
方がわかりやすければ、例えば>>718氏のあげた例:
 map<HWND, CWindow*> hwnd_to_wndptr_map;
 map<CWindow*, HWND> wndptr_to_hwnd_map;
のようなmap<>の使い方ができる、ということ。

# 「正しく動作する」 というのは、入れたはずのポインタがいつの間にか
# 消えてなくなったり、逆にコンテナから削除したはずなのにまだ残ってたり…
# などなどの怪しげな動作をせずに動く、ってこと、と思ってくれ。
742679:04/01/12 23:40
あー、かぶった。。。
743696:04/01/13 00:01
流れ流され〜

template
<
 typename T,
 typename SrcPointerType = T*
>
class CMustAssignedPointer
{
 private: typedef CMustAssignedPointer ThisType;
 private: SrcPointerType m_SrcPointer;
 private: CMustAssignedPointer();
 public: CMustAssignedPointer(const ThisType& rhs)
  : m_SrcPointer(rhs.m_SrcPointer)
 {
 }
 public: CMustAssignedPointer(SrcPointerType rhs)
  : m_SrcPointer(rhs)
 {
 }
};

int main()
{
 int* p = NULL;
 std::auto_ptr<int> p2(new int(100));

 CMustAssignedPointer<int> pNum = p;
 CMustAssignedPointer<int, std::auto_ptr<int> > pNum2 = p2;
}

なんでコピーコンストラクタが呼ばれちゃうんでしょうか?
>>740
だから、そんなもの作れたからって、何になる?
繰り返すが、意味があるかどうかではなくコンパイル通ったってだけな議論ならそろそろ見限るぞ

>>741
もしかして map<CWindow*, HWND>::iterator の大小比較が HWND の大小比較とでも思っているのか?

======================================

>入れたはずのポインタがいつの間にか
># 消えてなくなったり

( ´,_ゝ`)プッ
それじゃ定義を教えても理解できそうな御仁に見えないよ
>>743
いろいろまずそうなところを弄ったけど、
どうやっても何故かコピーコンストラクタが選ばれるっぽい
(そしてコンパイルに失敗する)。
コンパイラのバグかも?
>>744
逆だな。
おまえを見限った。
747739:04/01/13 00:28
>>744
> だから、そんなもの作れたからって、何になる?
739 で実例を挙げてるが
> std::map<T*, THandle> p2h;
こういう、ポインタをキーとしてハンドル値を引きたい場合に困るっつー話。
ま、お互い言うべきことは言ったと思うから、この辺で終わりにしましょうか>みなさん

まとめ

1. C++ の規格では、同一配列に属さないポインタは ==, != で比較することはできるが、
 <, <=, >, >= で比較した時の結果は未定義。
2. ただし、現実にはフラットなメモリアドレッシングを採用したアーキテクチャが主流なので、
 ほぼ全ての C++ 処理系で <, <=, >, >= でもポインタ間に全順序関係をつけられる。
3. C++ では <, <=, >, >= で順序関係をつけられないアーキテクチャも考慮して、ポインタ値を
 比較した場合に全順序関係が成立しない場合でも、std::less<T*>, std::greater<T*> を
 使えば全順序関係が成立するように規定している。
単にSTLの内部でoperator<を使ってないってだけの話だろ
引数が組み込み型かどうか判定する機能がtemplateにないからって真意で

747の言うべきこととやらが何なのかいまだに不明だが
言葉遊びが終わったならこっちも相手しつづける理由はない
>>744
>もしかして map<CWindow*, HWND>::iterator の大小比較が HWND の大小比較とでも思っているのか?

iteratorと大小比較は直接関係ないでしょう。
map<CWindow*, HWND>に必要なのはCWindow* の大小比較と思っていますが、それが何か。
>>748
なんでオマエは自分の馬鹿さ加減をそんなに宣伝したいのだね?
見てて面白いからいいけどさ。
いやー面白かった。

>>747
マジお疲れ。

>>748
( ´,_ゝ`)プッ
>>750
そんなこと言うなよ。
もっと逃げやすい状況にしてやれよ。
そろそろ 釣れた(藁 が来そうな悪寒
>>748
> 引数が組み込み型かどうか判定する機能がtemplateにないから
template <typename T> struct is_primitive_type { static bool const value = false; };
#define D_(type) template <> struct is_primitive_type<type> { static bool const value = true; }
D_(char); D_(signed char); D_(unsigned char); D_(unsigned short);
D_(short); D_(int); D_(unsigned int); D_(long); D_(unsigned long);
D_(float); D_(double);
#undef D_

#include <iostream>
struct foo {};
int main()
{
std::cout << is_primitive_type<int>::value << std::endl;
std::cout << is_primitive_type<foo>::value << std::endl;
}

ポインタかどうかを判定するのは、もっと部分特殊化で済むからもっと簡単。
この辺参照。

ttp://www.boost.org/libs/type_traits/index.htm
釣れたの前に自分以外は自作自演だと言い張るパターンが多い。
>>754
long double を忘れてるべ。
・相手は一人症候群
・自分は間違ってない症候群
・自分の文章が悪いのではなく、相手の読解力が無い症候群
・自分が最後の発言にならないと気がすまない症候群
【上級者です】知ったか厨の法則【たすけて】
>>756
げ、long double も標準規格の範疇だったのか。あと bool, wchar_t も脳内で
補完しといてね。
>>717
>>720
これってつまり
Cでは読み込みと書き込みのポインタを一つで扱うが
C++では読み込みと書き込みのポインタ(?)を別々に扱う
ってことでいいのかな?
>>760
むしろCの方がそうなってなかったのが不思議。
>>761
テープドライブを読み書きするときとか。
>>762
ああ、そう言えばCの一番古い奴は1972年頃に生まれたんだな。
scanf()関数はその時代の名残りで、それをキーボード入力用
に使うといろいろ不都合が出るからできるだけ使うなと言うように
なったっけ。そうでなくてもバッファオーバーランの危険性があるし。

FORTRANもパンチカード時代の名残りがあるしな。
テープに限らず、シーケンシャルな記録デバイスしか
無かった時代があったんだから仕方なかんべ。
>>745
うーぬ。解決しません。
とりあえずレスありがとうございましたの言葉だけ。
すみません配列を現そうとソース作ってたら挫折しますたヘタレです
#include <stdio.h>
main()
{
int a[5]={1,2,3,4,5};
for(a=0:a>5;a++){
a++;
}
printf("%d\n",a[5]);
}

はっきり言って自分何がやりたいのか意味不明です
頭がおかしいんでしょうか
>>766
適当な入門書を一冊じっくり理解できるまで読むことをお勧めします。
768766:04/01/14 01:09
なるほどキチガイでした
入門書を今日買ってきて読んでみます
>>766=768

次くるときは、せめて>>766がC++のソースにすら
なっていないことはわかるようになってね。
770766:04/01/14 02:27
>>769
そうですね何しろエラーが出て実行できませんから
struct Foo
{
static const int i=0;
static const int j=1;
}foo;

と宣言した構造体にアクセスするとき、
Foo::i とする方法と foo.i とする方法があると思いますが、
何がどう異なるのでしょうか?

両者の文法上の意味はわかるのですが、
静的メンバ変数のみの構造体のインスタンスなど、想像も出来ないのです・・・。
デフォルトコンストラクタが暗黙のうちに作られて何もせずに終わりでしょうか?
しかもインスタンスから静的メンバ変数にアクセスできるのも意味不明ですし・・・。
>>765
コンパイラは何を使った?BCC5.6.4ではちゃんとコンストラクタが
呼ばれるぞ。
Foo *p = 0;
p->i = 0; // ← thisにアクセスしないので落ちない

ってだけ
>>771
静的メンバ変数はクラスのインスタンスを持たなくても存在している。
>>771
乱暴な言い方すると
Fooという名前空間の中のグローバル変数。
>>774 >>775
お返事ありがとうございます
そこまでは分かるのですが、なぜクラスのインスタンスから静的メンバ変数に
アクセスできるのかが良く分からないのです。
静的メンバ変数はクラスのインスタンスを持たなくても存在しているのは理解しています、
でも、何でインスタンスから参照することが出来るのでしょう?
まったく別の概念で、別の場所にある変数ではないのでしょうか?
非常に危険極まりないことだと思うのですが・・・

インスタンスから静的メンバ変数にアクセス出来ないようにする方法はないのですか?
もし出来ないのなら、なぜ出来ないのでしょうか?
そして、どのようなイメージで理解すればよいのでしょうか?
メモリ配置的には確かにその通りなんだが、
オブジェクト指向的にその方が有用なこともある。
たとえば

class fixed_square {
public:
static int size;
};

class variable_square {
public:
int size;
};

としたとき(実際にはアクセサはさむが)
どちらもインスタンスから同じインターフェイスでアクセスできる。
776は、
なぜ、Class::Staticsだけではなく、instance.Staticsでも
アクセスできるんだ危ないじゃないか、といいたいのでは?
>>776
危険を承知で静的メンバ変数が必要な理由があるから。
インスタンスから静的メンバ変数にアクセスできないとしたら、
そりゃメンバ変数じゃないでしょ。

例えばインスタンスを10000個作ったとしても、静的メンバ
変数の実体は1個だけで、どのインスタンスから参照しても
同じに見える。これを利用して今いったいいくつのインスタ
ンスがあるのかを常に記録しておける。他にもいくつか利用法
がある。
>>778
あら、それだったら静的メンバ変数をprivate属性にしちゃえば
いいだけの話では。
>>777
おおお!そういうことでしたか。
さらには

class unit_square {
public:
const static int size=1;
};

な〜んていうふうにやっちゃうわけですね。
即レスありがとうございます。

しっかし、何も考えずに静的メンバ変数のアクセスにクラス名とインスタンス名を混在して使うと
とんでもないソースコードが生まれるわけですね・・・くわばらくわばら。

ところで、sizeof演算子をクラスに対して使った場合の正確な定義ってどこかにありますでしょうか?
プログラミング言語C++を探しても見つからなかったもので・・・
>>780
それでstaticな下駄雪駄を作ると。
そういう話じゃないわけだが。
静的メンバ変数は静的メンバ関数だけからアクセスする
癖を付けるのもいいかも。事実Singletonのデザインでは
そのようにしている。

但し複雑さというのは避けられないもので、静的メンバ変数
が他の箇所からほぼ同時にアクセスされる環境、すなわち
マルチスレッド環境では何らかの同期が必要となる。
784776:04/01/15 01:15
>>778
そのとおりです

>>779
その理由でしたらClass::Staticsだけでアクセスすればよいと思うのです

>>780
そしたら外から見えないし・・・

結局のところ>>777の理由からでしょうかね?
>>784
外から見えるようにするってあーた、それじゃわざわざ
静的にしろメンバ変数にする意味ないじゃん。
786776:04/01/15 01:23
>>783
>静的メンバ変数は静的メンバ関数だけからアクセスする癖を付けるのもいいかも。
>事実Singletonのデザインではそのようにしている。
そうですね。静的メンバ変数はprivateにして、
静的メンバ変数にアクセスするpublicな関数を用意するわけですね
しかし今度はClass::StaticFunctions()だけではなく、
instance.StaticFunctions()でもアクセスできる
という問題が発生してしまいまして・・・

まあ、幾分かましではありますが。
結論を手短にまとめると、>>784さんは

・クラスの静的メンバ変数が欲しい
・しかしそれはインスタンスから参照できないようにして欲しい
・しかもClass::Staticsという形でアクセスできるようにして欲しい

って所かな。そしたら、基底クラスでprotected属性で宣言し、
それを継承したクラスでのみインスタンスを作成する、という
方法ではだめなのかいな。
あーprotectedにするとClass::Staticsという形ではアクセスでき
ないか。
staticメンバ関数でアクセス方法だけ制限してやりゃええ話なのでは
>>789
詰まる所そうなりますね。それ以上はC++を使う人の責任で、
って事で。
static メンバ関数に
インスタンスからアクセスできなくする法はちと無理。
static と非 static でオーバーロードもできないし。
ああ、int型に限っては一つだけ方法がある。
クラス内 enum 値はインスタンスから参照できなかったはずだ。
>>792
こういう事でなくて?どうやってアクセス禁止になるんだろう。

#include <iostream>

class A {
public:
 enum E {a, b, c};
};

int main()
{
 A a;
 std::cout << a.b << std::endl;
}
無名でもできなかったっけ……
すまん、じゃあ勘違いだ
それじゃこんなのはどうだろ?
コンストラクタを返り値のように受けるのは微妙な問題があるけど
見た目上は要求の物に近いんでない?
複数の異なった値が欲しければ int に関しては
template < int n > と typedef を組み合わせれば
簡単なフレームワークで出来るはずだ。

class A {
public:
struct value{
operator int() const {
return 0;
}
};
};

int main() {
int v = A::value();
A a;
v = a.value(); // ここでエラー
}
テストコード。一応、gcc3.2(MinGW)で動作確認済み。

#include <iostream>

class Integer {
public:
friend struct setValue {
explicit setValue(int n) { n_ = n; }
};
friend struct getValue {
operator int() const { return n_; }
};
private:
static int n_;
};

int Integer::n_ = 0;

int main(void) {
Integer::setValue(4);
std::cout << Integer::getValue() << std::endl;
Integer i;
//i.setValue(4);
//std::cout << i.getValue(4) << std::endl;
}
>>795>>796
クラスのメンバに変換演算子のみを持つとそれは
初期化の時しか参照できないんだね。初めて知った。
しかもそれは一時変数で、目的の変数に代入が終了
したら消滅する。よくできたもんだ。

しかし>>796は残念だな。VC7.1でコンパイルできない。

c:\Documents and Settings\**\My Documents\Visual Studio Projects\Conversion\Conversion.cpp(9) : error C2391: 'Integer::setValue' : 'friend' は型定義中には使えません。
c:\Documents and Settings\**\My Documents\Visual Studio Projects\Conversion\Conversion.cpp(12) : error C2391: 'Integer::getValue' : 'friend' は型定義中には使えません。
c:\Documents and Settings\**\My Documents\Visual Studio Projects\Conversion\Conversion.cpp(24) : fatal error C1903: 直前のエラーを修復できません。コンパイルを中止します。
>>797
エラーメッセージ読んだ感じ
定義後に friend 宣言すれば問題ないんとちゃう?
(それできなかったら多くの内部型が困りそうだ)
>>798
結果だけ書くと、VC7.1はfriend宣言取ってもコンパイルできた。
事後のfriend宣言でも通ったけど、gccと挙動が違う。
>>784の件についてだが
コンストラクタをprivateとかにしてインスタンスを生成できなくすればいいんでないの?
>>800
いや、インスタンスが生成できて、かつstaticなメンバ変数
にインスタンスからアクセス不可能にしたかったようです。
a.b とか pa->b という記法で static member変数を参照できる、
というのがキモチ悪かったっていうことだと思います。

漏れも少しキモチ悪い。virtual static member variable なんてのが
あるならともかく。
functionはともかくvariableはないだろw
>>802
気持ち悪いか。感覚の違いだな。
俺はそう書けて当然だと思う。統一が取れてて。
805デフォルトの名無しさん:04/01/15 21:32
質問です。intやcharで定義する変数名は英語ならどんな名前でもいいんですか?

int ten;
int x;

char name;
char a;

are you ok?
>>805
名前付けルールはそのコードを維持する人が良いと思えば
何語だってかまわんよ。使える文字を使ってさえいれば。
>>806
thank you
>>803
>functionはともかくvariableはないだろw

いや、こんな感じ。vtbl みたいなクラス毎の変数用ストレージ。
struct A {
 virtual static const int object_id = ID_A;
};

struct B : public A {
 virtual static const int object_id = ID_B;
};

A* pa = new B;
pa->object_id // ID_B になる
809超初心者:04/01/15 22:51
プログラミングの仕方が全然わからないんですが○×ゲームでかならず引き分けるプログラムをどのようにプログラミングしたらいいか教えていただけませんでしょうか。
「必ず引き分ける」なんて結果のみを期待されても答えられない。
その手の手数の少ない対戦ゲームなら
素直にMAX-MIN法を使ってゲーム木を探索して手を決定するとか。

>○×ゲーム
3*3の三目並べのこと?
ならウォー・ゲームでも繰り返し鑑賞しなさい
812デフォルトの名無しさん:04/01/15 23:58
おながいします。
テンプレートの引数にテンプレートを指定することはできないのですか?
CList<CArray<CPoint,CPoint>> m_list;
みたいな。。。
>>812
できます。
814812:04/01/16 00:10
レスありがとうございます。
VC++6.0なのですが
error C2146: 構文エラー : ',' が、識別子 'm_list' の前に必要です。
みたいなエラーが出てコンパイルできないのですが...
だまされないように。できません。
×:>>
○:> >
VC6ではテンプレートのネストはできない。
もっと新しいコンパイラを使え。
できるっつーの
819812:04/01/16 00:26
>>816
どうもありがとう(TT)
でも今度はリンクができなくなってしまったのですが・・・
820812:04/01/16 00:30
できました。
教えてくださったみなさんどうもありがとう。。。
821デフォルトの名無しさん:04/01/16 00:51
すみません。また812です。
別件なのですが、テンプレートクラスを含んだcppファイルを
コンパイルはできるのですが、それを使用したcppをコンパイルして
リンクしようとすると、シンボル未解決でリンクエラーになります。
何か考えられる原因はあるでしょうか?
>>821
エラーメッセージぐらい貼れよ
823921:04/01/16 01:00
>>822
すいません。m(__)m
通常のマングリングコードが出てシンボルは未解決ですって
いうエラーです。
というか今解決しました。hとcppにわけていたのですがhにまとめたら
うまくいきました。でもなんでなんでしょう???
あらゆるtemplateは定義までヘッダにおいとかないと
たいていのコンパイラで上手くリンクまでできない。
825921:04/01/16 01:02
そうなんですね。知りませんでした。。。
826821でした:04/01/16 01:05
遅くにどうもありがとう。。。
827デフォルトの名無しさん:04/01/16 01:21
class CObjAddr{};
class CPtrA{public: operator CObjAddr() const { return CObjAddr(); };
class CPtrB{public: operator CObjAddr() const { return CObjAddr(); };
bool operator== (const CObjAddr& lhs, const CObjAddr& rhs) { return true; }
int main()
{
CPtrA a;
CPtrB b;
if (a == b);
return 0;
}

はコンパイルできるのですが

template <typename T> class CObjAddr{};
template <typename T> class CPtrA{public: operator CObjAddr<T>() const { return CObjAddr<T>(); };
template <typename T> class CPtrB{public: operator CObjAddr<T>() const { return CObjAddr<T>(); };
template <typename T>
bool operator== (const CObjAddr<T>& lhs, const CObjAddr<T>& rhs) { return true; }
int main()
{
CPtrA<int> a;
CPtrB<int> b;
if (a == b);
return 0;
}

になると途端に==演算子を見つけられなくなります。
正確に言うと上の方のコードのoperator==にtemplate <typename T>と付けた時点(型名にはTがかかっていない状態)で
既に==演算子を見つけられなくなります。
下の状態で a == b をそのままの形で(明示的にキャストせずに)コンパイルできるようにしたいのですが
何か方法はないでしょうか?よろしくおねがいします。
エラーメッセージをよく読んで } の数を数えてみることを勧める。
つーか上のコードよく通ったな。
829827:04/01/16 03:54
>>828
ここに載せられるように簡略化したときにちょっと失敗しました。
class CObjAddr{};
class CPtrA{public: operator CObjAddr() const { return CObjAddr(); }};
class CPtrB{public: operator CObjAddr() const { return CObjAddr(); }};
bool operator== (const CObjAddr& lhs, const CObjAddr& rhs) { return true; }
int main()
{
CPtrA a;
CPtrB b;
if (a == b);
return 0;
}

template <typename T> class CObjAddr{};
template <typename T> class CPtrA{public: operator CObjAddr<T>() const { return CObjAddr<T>(); }};
template <typename T> class CPtrB{public: operator CObjAddr<T>() const { return CObjAddr<T>(); }};
template <typename T> bool operator== (const CObjAddr<T>& lhs, const CObjAddr<T>& rhs) { return true; }
int main()
{
CPtrA<int> a;
CPtrB<int> b;
if (a == b);
return 0;
}
ですね。質問の本質的内容は変わりません。よろしくお願いします。
たぶん暗黙の型変換とテンプレート引数の双方のマッチングが
絡み合って適用されないんだな。

キャストをしたくないのなら、
明示的にテンプレート引数を指定して実体化させるか、
別の関数を挟むかするしかないだろ。
template <typename T_>
class CPtrA
{
public:
  operator CObjAddr<T_>() const { return CObjAddr<T_>(); }

  bool operator==( const CObjAddr<T_>& rhs ) const {
    return true;
  }
};
にするとか・・・。めんどいかね・・・。