08/03/09 19:37:43
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレに
お願いします。
2:デフォルトの名無しさん
08/03/09 19:38:18
■基本■
[C++ FAQ]
URLリンク(www.parashift.com)
URLリンク(www.bohyoh.com) (日本語)
Cとその仕様を比較しながらの解説なので分かりやすい。
***** 質問の前に必ずこの二つに目を通してください *****
[C/C++ リファレンス]
URLリンク(www.cppreference.com) (英語)
URLリンク(www.cppll.jp) (↑の日本語訳だけど最新は反映しない)
[禿 Stroustrup]
URLリンク(public.research.att.com)
[C++ International Standard]
URLリンク(www.iso.org)
[JTC1/SC22/WG21 - C++]
URLリンク(www.open-std.org)
ここから規格の最新(2003より新しい)ドラフトがダウンロードできる。
[JIS X3014]
URLリンク(www.jisc.go.jp)
ISO規格の日本語訳。JIS X 3014:2003はISO/IEC 14882:2003 (E)に対応。
3:デフォルトの名無しさん
08/03/09 19:38:41
■Books(Templateまわり)■
Effective STL
URLリンク(www.amazon.com)
URLリンク(www.amazon.co.jp) (翻訳)
Modern C++ Design
URLリンク(www.amazon.com)
URLリンク(www.amazon.co.jp) (翻訳)
C++ Templates
URLリンク(www.amazon.com)
C++ Template Metaprogramming
URLリンク(www.amazon.com)
4:デフォルトの名無しさん
08/03/09 19:39:05
■Libraries■
[Boost]
Boost URLリンク(www.boost.org)
(日本語) URLリンク(www.kmonos.net)
(日本語) URLリンク(shinh.skr.jp)
[標準ライブラリ]
SGI-STL URLリンク(www.sgi.com)
STLport URLリンク(stlport.sourceforge.net)
GNU libstdc++ URLリンク(gcc.gnu.org)
Apache STDCXX URLリンク(incubator.apache.org)
STLFilt URLリンク(www.bdsoft.com)
(日本語) URLリンク(www005.upp.so-net.ne.jp)
(日本語) URLリンク(www.wakhok.ac.jp)
[Loki]
URLリンク(sourceforge.net)
LokiPort-MSVC6sp5 URLリンク(fara.cs.uni-potsdam.de)
5:デフォルトの名無しさん
08/03/09 19:39:25
STLつかうと一気に実行ファイルサイズが10倍に?!
環境によるだろ。
俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力
ランタイムを使用するようにして使っているが、例えばstd::vectorを
使っても使わない時と比べ10Kほどしか増えない
すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。
とかいうエラーが出るんだけどこれってどうすればいいの?
#include <stdafx.h>
後死ね。
言葉が悪いな。それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。
6:デフォルトの名無しさん
08/03/09 19:43:29
前スレ
C++相談室 part60
スレリンク(tech板)
7:デフォルトの名無しさん
08/03/09 19:46:54
>>6
サンクス、連投で制限食らった
8:デフォルトの名無しさん
08/03/09 20:02:21
>>前スレ1000
とりあえず、お前が俺の言っていることを理解出来ていないことだけは分かった
お薦めの本があって、それを教えることには全く反対しないが、
自分で調べたり、情報を探したりしようとしない奴は
大体どうしようもない
一応補足
前スレ984のように聞いてみること自体は別に良いと思う
本を紹介してもらわないと先に進めない、ということでなければ
9:デフォルトの名無しさん
08/03/09 20:05:41
お前のポリシーはどうでもいいよ
10:デフォルトの名無しさん
08/03/09 20:06:48
そういや、こういうヤツがいるから初心者歓迎スレが出来たんだったな
11:デフォルトの名無しさん
08/03/09 20:14:48
ポリシーじゃねぇよ・・・
無能にレスしても無駄のようだな・・・
>>10
初心者に本だけでなく入門サイト探してみたら?って言うのは
アドバイスにならないのか?
自分自身の経験から言っているんだけど
ある程度理解出来てくるとcppllのアーカイブとかも参考になるし
12:デフォルトの名無しさん
08/03/09 20:31:24
おとなしく初心者歓迎スレかオススメ図書スレに誘導してやれよ
今回の様な議論が過去あったからこそそういったスレがあるんだから
13:デフォルトの名無しさん
08/03/09 20:40:52
誘導済みだろ?
俺は別に質問者にレスしてるつもりないし・・・
前スレの985のレスが気に食わない人が居るようなので、
レス返してるだけ
14:デフォルトの名無しさん
08/03/10 00:04:40
>>13
案外質問した人が突っ掛ってたりしてなw
んなわけないか。
15:デフォルトの名無しさん
08/03/10 01:09:34
他スレでis-a、has-aで継承やメンバを考えるみたいな話が合ったんですが、
doはどういう風に処理したらいいでしょうか
アクションゲームとかでAn enemy moves.(敵は動く)とした場合、
moveメソッドはenemyオブジェクトの位置を示すメンバ変数を操作すると思います。
すると、moveはenemyオブジェクトのメンバ関数であるべきと思えるのですが、
他のオブジェクトの位置とかが影響する場合、
enemyオブジェクトをメンバにもつクラス(WorldとかGameとか)に、
全てのオブジェクトを動かすメンバ関数を用意した方が、
他のオブジェクトを参照でき適切に処理できそうです
このような機能を持つメソッドを、皆さんはどの位置に配置していますか?
16:デフォルトの名無しさん
08/03/10 01:17:01
enemyのmoveメソッドはそのままで
WorldやGameからすべてのenemyのmoveメソッドを呼ぶ様にすればいいんじゃね?
ていうかC++関係ないな
17:デフォルトの名無しさん
08/03/10 01:23:43
>>15
もし本当にゲームのことだったら
スレリンク(gamedev板)
とかで聞いた方が良さそう。
それかこの板のクラス設計とかのスレ。
俺だったら、大まかにStrategyパターン的な感じで書くかな。
enemyとかのユニット情報を持った環境(orフィールド)オブジェクトを
参照していじる敵戦略クラス・・・とか。
18:デフォルトの名無しさん
08/03/10 01:31:46
>>16
すみません、自身がCからC++に移行して、
クラス設計に右往左往しているもので、ここで聞いてしまいました
>>17
あ、そんなスレがあったとは知りませんでした
moveメソッドは引数にしたがってオブジェクトの変数を変えるだけ
moveメソッドに渡す引数を敵戦略クラスないし、Worldクラスで決定するって方向で考えて見ます
(moveメソッドの内容が二行で終わりそうだ……。他のメソッドとまとめよう)
ありがとうございました
19:デフォルトの名無しさん
08/03/10 01:34:51
>>18
ちなみに、17のはゲ製板のスレね。
20:デフォルトの名無しさん
08/03/10 01:40:44
飛んできたのはおそらく同じ板のシューティング製作スレだなw
21:17
08/03/10 02:11:11
ターン制で移動先選択→攻撃みたいなの想定してました/(^o^)\
敵戦略クラスは忘れた方が良いw
22:デフォルトの名無しさん
08/03/10 03:05:22
Class().Method();
なんて書けたんだね、、、知らなかったよ(;´Д`)
23:デフォルトの名無しさん
08/03/10 03:20:08
式が何を意味するかによる。Class()がインスタンスなら当然ドットを付けてメンバにアクセスできる。
一通り文法をかじったなら、今度は仕様書を読んでそれを確かなものにした方がいい。流れとしては。
24:デフォルトの名無しさん
08/03/10 22:21:40
ぁぁ、ごめん。はしょりすぎた。
class Class
{
public:
int Method();
};
こんなので、
void F()
{
printf( "%d\n", Class().Method() );
}
な感じ。
25:デフォルトの名無しさん
08/03/10 22:38:15
printf("%d\n", int(5));
な感じ?
26:デフォルトの名無しさん
08/03/10 22:47:08
一時オブジェクトが近々move semanticsな感じ?
27:デフォルトの名無しさん
08/03/10 23:37:58
異なるクラスのオブジェクトをひとつの配列(vector,list)で管理することは出来ないのでしょうか
a[0]はclassA,a[1]はclassB,a[2]はclassC、……という風に
classA、classBは同じpublicなメンバを持っているのですが、
メンバ関数の中身とそこで使うprivateなメンバが異なっています
28:デフォルトの名無しさん
08/03/10 23:49:47
>>27
そういうのこそ、ポリモーフィズムでしょ
29:デフォルトの名無しさん
08/03/10 23:59:11
>>28
関数の多重定義のことでしょうか
ClassAとClassBの異なるメンバもひとつのクラスにまとめて、
使わないメンバがあっても気にしない、という方針でもいいんですが、
無駄にメモリを消費するのがイヤなもので
30:デフォルトの名無しさん
08/03/11 00:01:24
全く関連のないクラスを1つの配列に入れるという時点でかなりおかしいと思う。
関連というか共通項があるからこそ1つの配列に入れるんだろう?
31:デフォルトの名無しさん
08/03/11 00:06:44
>>29
仮想関数ってやつだ。
class Base {
public:
virtual ~Base() {}
virtual void func() = 0; // 共通のメンバ関数
};
class A : public Base {
public: virtual void func() { /* classAの処理 */ }
private: /* classAのメンバ変数 */
};
class B : public Base {
public: virtual void func() { /* classBの処理 */ }
private: /* classBのメンバ変数 */
};
このようにしておいて、たとえば
Base* p1 = new A;
Base* p2 = new B;
とすれば、
p1->func(); // A::funcが呼ばれる
p2->func(); // B::funcが呼ばれる
となる。
あとはvector<Base*>にすれば万事解決では。
32:デフォルトの名無しさん
08/03/11 00:09:10
boost::ptr_vector だと勝手に delete してくれるから楽だよ。
33:デフォルトの名無しさん
08/03/11 00:43:37
>>30
アクションゲームで
A:単純な移動しかせず体当たりでダメージを生む敵
B:主人公の位置などを頼りに複雑なアルゴリズムで動き多彩な攻撃をする敵
こんな感じでAの方が圧倒的に必要なメンバ変数が少なく、
かつAの方が数が多いので、Bに合わせてメンバ関数を増やすとメモリを食らってしまうのです
>>31
>Base* p1 = new A;
AがBaseを継承していると、こんな代入も可能なのですか……
ありがとうございました
>>32
ググってみましたが、new演算子を使いまくるなら、便利そうですね
仕様に慣れるよう練習してみます
あちがとうございました
34:デフォルトの名無しさん
08/03/11 00:44:13
誤字修正
×Bに合わせてメンバ関数を
○Bに合わせてメンバ変数を
35:デフォルトの名無しさん
08/03/11 02:31:06
>>33
とりあえず
継承、多態(ポリモーフィズム)、オーバーライド
等を調べるんだ
AとBの共通する部分を基本クラス(やinterface)としてくくりだせ
36:デフォルトの名無しさん
08/03/11 11:10:02
エピステーメー氏の「C++言語のカラクリ」の話題出た?
なめて読んでたら「自己記述の必然性」が全く理解できない。
どうにか「だから単純なC++→C」のコンバーターじゃ駄目なんだよって
一言で説明できないか?
37:デフォルトの名無しさん
08/03/11 11:49:30
C++をC++で記述できないとだめだということ?
何だかよく分からないな。でもあの人はたまに哲学よりのトンデモを平気で書いたりするから気にしちゃいけないよ。
38:デフォルトの名無しさん
08/03/11 12:02:24
Cだけではtrr..catch..throwが実現できなかったって話だろ。
でも話題が古いなあ。
39:デフォルトの名無しさん
08/03/11 12:23:12
自己記述できることが○○だ(スバラシイとか完備だとか)
って誰かに刷り込まれたんかな
頭悪いな
40:デフォルトの名無しさん
08/03/11 12:26:33
コードジェネレータ通すとデバッグがやりにくそう
41:デフォルトの名無しさん
08/03/12 00:28:22
VMのスタック上で記号処理を介せば
殆どの言語は自己記述可能だが
と書けばミもフタもないのか
42:デフォルトの名無しさん
08/03/12 02:44:49
IO機能がないんですがどうすればいいですか。
43:デフォルトの名無しさん
08/03/12 05:26:59
URLリンク(www.google.com)
44:デフォルトの名無しさん
08/03/12 05:33:36
42は41へのレスなんじゃなかろうか
45:デフォルトの名無しさん
08/03/12 05:48:23
orz
46:デフォルトの名無しさん
08/03/12 10:24:06
自己記述ってどんなの?
47:デフォルトの名無しさん
08/03/12 11:16:52
ある言語やその処理系でその言語を実行できる処理系を書くことだお
48:デフォルトの名無しさん
08/03/12 13:28:47
多分要はメタプログラミングは必要だから出てきたんだ、偶然や酔狂じゃない。
ってことを言いたいんだろ?読んでないけど。
49:デフォルトの名無しさん
08/03/12 21:59:43
あれ?なんかtemplateで遊んでたらメタプログラミングできちゃったぞ
って感じ
50:デフォルトの名無しさん
08/03/12 22:01:01
typedef std::map<size_t,Dummy> DummyMap;
DummyMap dmap;
....
DummyMap::iterator it = dmap.find(index);
Dummy& dummy = (it != dmap.end()) ? it->second : dmap[index];
っていうこと(イメージ)をしたいんだが、\
findして、insertすると少なくとも2回の走査が行われていて、無駄な感じがする。
どうすべきか、アドバイスをくだされ。
51:デフォルトの名無しさん
08/03/12 22:02:34
趣旨を間違った。
これじゃ普通にdmap[index]すればいいじゃねーか。
出直してくる。
52:デフォルトの名無しさん
08/03/12 22:41:37
韓国人宇宙飛行士が国際宇宙ステーションに搭乗する際の活動に関する日本韓国間の協力について
URLリンク(www.enjoykorea.jp)
日本の大事な税金で作ったものを何で韓国人にタダでつかわせるんだ!
苦情メールを送ろう!
JAXA URLリンク(www.jaxa.jp)
文部科学省 URLリンク(www.mext.go.jp)
御意見・お問い合わせ専用メールアドレス voice_atmark_mext.go.jp
全く他人事じゃないんですけど>ロシア
宇宙ステーションをただで使わせて写真とらせるとかいってますが・・
抗議してくれ。
朝鮮人どもまじで死んでくれ。
53:デフォルトの名無しさん
08/03/12 23:42:33
>>51
定型はこう、かな
iterator it = map.lower_bound(key);
if(it == map.end() || it->first != key) {
it = map.insert(it, Dummy());
}
Dummy &d = it->second;
54:デフォルトの名無しさん
08/03/13 00:02:54
> it->first != key
これは問題なければ良いんだけど、正確にはlessを使えとかそういう話、無かったっけ?
55:デフォルトの名無しさん
08/03/13 00:24:47
it->first != key
lower_boundの戻り値はpairじゃないよな。確かキーだよな。
ソート基準がデフォのlessならこうか。
if(it != map.end() || !(key < *it)) {
//found
} else {
//not found
}
56:デフォルトの名無しさん
08/03/13 00:26:26
||じゃなくて&&だわ
if(it != map.end() && !(key < *it)) {
//found
} else {
//not found
}
57:デフォルトの名無しさん
08/03/13 00:37:32
>>55
lower_bound()の戻り値はpairだよ。
・・・というより、map<k, v>::value_typeがpair<k, v>だ、と説明するほうが、根本的で適切かな。
std::コンテナ::iteiratorは、std::コンテナ::value_typeのポインタ的に動作するわけだから。
>>53-54
「厳密には」こう書くべき。
if (it == map.end() || map.key_comp()(key, it->first) {
58:デフォルトの名無しさん
08/03/13 00:38:36
ごめん訂正。
- map<k, v>::value_typeがpair<k, v>
+ map<k, v>::value_typeがpair<const k, v>
59:デフォルトの名無しさん
08/03/13 00:46:26
>>57
ああ、そうだね。elementの型がpairだた。スマソ。
60:デフォルトの名無しさん
08/03/16 05:51:19
テスト
61:デフォルトの名無しさん
08/03/16 05:55:48
class B;
class A
{
B b;
};
class B
{
A a;
};
と書いたところ、
エラー出ます><。
どう対処すればいいですか?
62:デフォルトの名無しさん
08/03/16 06:04:28
よく考えようぜ。
A の中に B がある。
その B の中に A がある。
その A の中に B が・・・
あり得ない。
とりあえず何をしたいのか整理しよう。
大抵の場合は、
1. クラス設計を変更する。
2. a と b のどちらかを参照にする。
のどちらかになる。
63:デフォルトの名無しさん
08/03/16 06:31:59
haskellを使う
64:デフォルトの名無しさん
08/03/16 07:41:30
>>61
Aの中に持ちたいのはBそのものじゃなくて、Bの参照なんじゃね?
65:デフォルトの名無しさん
08/03/16 15:02:01
>>62
循環して持ちたいのはよくあること。
やるなら>>64のようにすればいい。
同じような質問見つけてきたんで参考にどうぞ。
URLリンク(www.atmarkit.co.jp)
66:デフォルトの名無しさん
08/03/16 15:45:33
62にそう書いてるじゃん
67:デフォルトの名無しさん
08/03/17 03:49:28
くだらない質問で申し訳ないのだけど、どなたか教えてください
クラスのコンストラクタで関数名の後ろにつけている初期化みたいなものの意味を教えてください
hoge::test() : a(0),b(0),c(0)
{
...
}
この場合だとa=0,b=0,c=0?
だとしたらなぜ...のところに書かないのですか?
68:デフォルトの名無しさん
08/03/17 04:07:50
test
69:デフォルトの名無しさん
08/03/17 04:11:10
test()じゃエラー出ると思う
hoge::hoge() : a(0),b(0),c(0)
{
...
}
のことだよね
aが変数だと問題ない?けど
aがクラスの場合、aのコンストラクタに0という引数渡すということ。
class a{
public:
a(int value);
};
みたいなクラスの場合、aのコンストラクタに数値渡さないと作成できないし
70:デフォルトの名無しさん
08/03/17 04:29:44
変数とクラス名が同じだとエラー出るや
class A{
public:
A(int value);
};
class hoge
{
A a;
public:
hoge() : a(0)
{
...
}
};
ってこと
この場合
...の所に a = 0; って書けない
71:デフォルトの名無しさん
08/03/17 08:54:36
>>67
前者は初期化で、後者は何らかの初期化、または未初期化で構築の後、代入だな。
どちらでも良い場合はあるけど、意味は明確に違う。
例えばconstが絡んだ場合とか、
class hoge{
const int a; //constなので代入できない。
};
>>69のようにメンバの構築に引数が必要な場合とか。
未初期化な変数を嫌ったり、デフォルトコンストラクタの後に代入するような
効率の悪さを嫌ったり、色々あるからできるだけ初期化を使う。
72:デフォルトの名無しさん
08/03/17 10:11:47
CとC++の違いを徹底解説!みたいな本に
Class::Method():field(0),field1(0)
{
}
なんて書いてあってさ、
何だよコンパイラバグってんじゃねーか!とか思ったころがあった
73:デフォルトの名無しさん
08/03/17 10:39:23
>>72 本の名前晒しといてくれ。
74:デフォルトの名無しさん
08/03/17 10:40:42
ていうかさ、constメンバや参照メンバもそうだけど
基底クラスの初期化も、この形式じゃないと出来ないよ。
もちろん、引数なしのデフォルトコンストラクタでの初期化は可能だけど。
75:72
08/03/17 11:55:05
「オブジェクト指向言語C++入門 Cとの違いを徹底追求」
これかな。
やっぱり古いのもあってか、<string.h>とか、
namespace、例外の話はまったくなかった。
それ意外と、多少の誤植を除けば、解り安くもなければ解りづらくもない中立的な本だった。
まぁ、今となっては読むべき本じゃないわな
76:デフォルトの名無しさん
08/03/17 13:02:50
低レベルな質問は初心者スレでやれ
77:デフォルトの名無しさん
08/03/17 15:16:38
>>76
おまえが、↓に行け
C++上級者が集まるスレ
スレリンク(tech板)
78:デフォルトの名無しさん
08/03/17 16:49:26
関数の戻り先アドレスがバッファオーバーランで壊されているようなんですが、どこで壊されているのかが分かりません。
a(){
b();
}
b(){
// ログに戻り先アドレスを記録
/* 処理1 */
// ログに戻り先アドレスを記録
/* 処理2 */
// ログに戻り先アドレスを記録
return;
}
あたりをつけるために、上のように処理の区切りで関数の戻り先アドレスをログにはき出そうと思うんですが、
戻り先アドレスをどのように参照していいかが分かりません。
もし分かりましたら、参照方法を教えてください。
よろしくお願いします。
79:デフォルトの名無しさん
08/03/17 17:02:46
環境に依存します
80:デフォルトの名無しさん
08/03/17 17:17:10
>>78
そこまで推測できているならデバッガでスタックにトリガ張ればすぐだろうし、
そうでなくてもコンパイラにスタックのチェックをするオプションがあったりしないか?
そもそもバッファオーバフローだと判っているなら関数内のポインタを全部洗えばいいだけじゃん。
# 巨大関数だったらしらねw
81:デフォルトの名無しさん
08/03/17 17:27:32
>>79
失礼しました。
Windows2000 VC++6です。
>>80
それが、1ヶ月に1度位しか発生しないエラーなのでトレースが困難なんです。
各所にログを埋め込み、関数から戻ってこないのは確認できたので、戻り先アドレスが壊されているらしいと推測したんです。
次はどこで壊されるかをログに記録し、また1ヶ月待ってみようと思いましてw
82:デフォルトの名無しさん
08/03/17 17:30:16
espでも記録しておくとか
83:デフォルトの名無しさん
08/03/17 17:46:56
>>81
>79の時点でスレ違いだと気付こう。
>そうでなくてもコンパイラにスタックのチェックをするオプションがあったりしないか?
84:デフォルトの名無しさん
08/03/17 18:21:17
>>83
申し訳ありませんでした。
色々なアドバイスありがとうございました。
85:デフォルトの名無しさん
08/03/17 21:45:50
const T &なメンバをもつクラスを作ったんだが、
ひょっとして、コピーする手段がない?
86:デフォルトの名無しさん
08/03/17 21:51:54
クラス初期化にしかconst T &は初期化できないから
まぁなんというか頑張れ
87:デフォルトの名無しさん
08/03/17 22:03:17
コピーコンストラクタならおkだが、operator=はダメだろうな
88:デフォルトの名無しさん
08/03/17 22:47:28
const_ca
89:デフォルトの名無しさん
08/03/18 00:27:05
なんで&があるん?
*だけじゃ駄目なん?
90:デフォルトの名無しさん
08/03/18 01:01:24
駄目です
91:デフォルトの名無しさん
08/03/18 01:23:09
なんで
92:デフォルトの名無しさん
08/03/18 01:24:56
インラインアセンブラ使えばコピーできないことはないだろうが
当然おすすめはしない。
93:デフォルトの名無しさん
08/03/18 01:32:09
関数gがコンパイルエラーになります。なぜですか?不可解です。
class X {
protected:
int val;
};
class Y : public X {
public:
void f(Y* p) { p->val = 0; } // OK
void g(X* p) { p->val = 0; } // エラー
};
94:デフォルトの名無しさん
08/03/18 01:53:29
X::valはYから見ればprivate
Y::X::valはYから見ればpublic
95:デフォルトの名無しさん
08/03/18 01:55:26
あ、いや、privateというべきじゃなくprotectedでいいのかな。どっちだろ。
いずれにせよYからX::valは触れない。Y::X::valなら触れる。
96:93
08/03/18 02:05:40
>>95
やっぱりそうですか。なんとなく奇妙な言語仕様に思えるのですが。。。
97:デフォルトの名無しさん
08/03/18 02:21:17
じゃなぜこういう風に難解なルールになっているか逆に考えてみればわかる。
class Y2 : public X {
void f(Y* p) { p->val = 0; }
};
というXを継承した別のクラスを作ってみよう。YとY2は別のクラスなのでY2から
Yのprotected属性のメンバ変数が変更出来てはまずいのに、もしこのような
ルールがなかったら上の例で可能になってしまう。
モジュールの隠蔽が破られないように特別なルールが作られているわけだ。
98:93
08/03/18 02:33:25
なるほど。なんとなくですが、分かりました。
99:デフォルトの名無しさん
08/03/18 07:13:26
fseekgでstr.length()分を戻したいのですけど、
単にマイナスをつけて、-str.length()とするとイミフな数値しか出ません。
何でうまくいかないんでしょうか?
100:デフォルトの名無しさん
08/03/18 07:39:13
事故解決しました。 length()が返すのはsize_typeで、
size_typeはsize_tのunsigned intみたいだからですね。
101:デフォルトの名無しさん
08/03/18 20:26:40
出しかたによる。
102:デフォルトの名無しさん
08/03/18 20:37:42
>>100
環境依存の話すんなくそったれ
103:デフォルトの名無しさん
08/03/18 22:02:40
この言語機能多すぎじゃね?
104:デフォルトの名無しさん
08/03/18 22:14:29
必要な部分だけ使え
105:デフォルトの名無しさん
08/03/18 22:23:31
>>102
少なくともsize_typeは符号無しということは標準で決まっている事柄だったと思う。
106:デフォルトの名無しさん
08/03/18 23:49:31
>>105
unsigned intとどこに書いてある?
107:デフォルトの名無しさん
08/03/19 00:00:40
お前は何を言ってるの?
108:デフォルトの名無しさん
08/03/19 00:22:24
>>106
それは規格のどこにも書いていないが、
例えばもし99=100が使っている実装のsize_typeが
仮にunsigned longやunsigned shortだったとしても、
99=100は同じように質問して同じように解決していたに違いない。
たまたま100の使っている実装でsize_typeがunsigned intだったこと以外は
標準C++で普遍的に成り立つ話じゃないか。
109:デフォルトの名無しさん
08/03/19 00:24:39
size_typeは符号なし整数。
ただしbit数は決まってない。
110:デフォルトの名無しさん
08/03/19 06:33:43
>>108
頭の悪い子って、「話の行きがかりで登場したディテール」と「そのディテールに依存した話」の違いが
わからないから困るよね。
少なくとも、「環境依存の話すんなくそったれ」と「unsigned intとどこに書いてある?」の2レスより、
「でも規格で決まってるのはunsignedってことだけだから注意」とか書くほうが簡潔で有用。
非・馬鹿は最初からこう書く。
111:デフォルトの名無しさん
08/03/19 07:24:46
size_t が unsigned long のこともよくあるしな。
112:デフォルトの名無しさん
08/03/19 09:04:06
unsigned short だったりすると -length() しても int 型で普通に負の数になったりして。
113:デフォルトの名無しさん
08/03/19 12:28:38
std::cinで文字や数値を入力するとバッファに改行文字が残るようで、
その後に std::getline(std::cin, buf, '\n'); とかやらせると残った改行文字だけ読み込んでしまいます。
バッファをクリアする方法がないかと調べてみたのですが、
環境に依存せず確実にクリアする方法はない、という記述がありました。
こういう場合はそもそもstd::cinを使わないようにするのがよいのでしょうか?
fgetsとかを代わりに使えば改行文字まで読み込んでくれるみたいなのですが、
std::cinの方がすっきりしたコードになるので、他に問題を回避する方法がないか探しています。
114:デフォルトの名無しさん
08/03/19 12:45:02
>>113
cin.ignoreを呼ぶとかcin.getを繰り返すとかで十分では?
115:デフォルトの名無しさん
08/03/19 12:49:09
ああ、なるほど。
この場合はバッファに残るのが改行文字一個だけと分かってるから、それで十分なんですね。
ありがとうございました。
116:デフォルトの名無しさん
08/03/19 15:15:14
cinから一行読み込み+istringstreamで良くね?
string line;
getline(cin,line);
stringstream linestream(line);
117:デフォルトの名無しさん
08/03/20 15:40:59
#define Max 1000
みたいなのを、グローバル変数を使って
const int Max = 1000;
とした方が良い(型指定ができるから)、と読んでる本で出てきました。
色んな所で「グローバル変数はできるだけ使うな」と言われていたのでびっくりしてしまったのですが、
こうやってconstにして#defineの代わりにするのは例外的によく使われるものなのでしょうか?
118:デフォルトの名無しさん
08/03/20 15:46:50
defineよりはマシってだけの話。
119:デフォルトの名無しさん
08/03/20 15:52:08
グローバル変数の議論とはまた別の話しだろ
120:デフォルトの名無しさん
08/03/20 15:56:36
>>117
グローバル変数がダメなだってだけ覚えてて、なぜダメなのか考えたこと無いみたいだね?
大雑把に言うとどこで変更してるか分からないから把握しづらいといったとこです
const つけた場合(やろうと思えばできるけれど)変更できないので、そういう害は無い
121:デフォルトの名無しさん
08/03/20 15:58:48
あほすぎるw
122:デフォルトの名無しさん
08/03/20 16:53:57
別の翻訳単位で参照する可能性のある“変数”ならグローバル変数を使う。
別の翻訳単位で参照する可能性のある“数値”なら#define定義のあるヘッダを各自インクルードすればいい。
123:デフォルトの名無しさん
08/03/20 17:11:37
>>122
なに言ってんの?w
124:デフォルトの名無しさん
08/03/20 17:12:31
const ついてるやつはグローバル定数と呼ぶべきもの。
125:デフォルトの名無しさん
08/03/20 17:17:00
>>117
グローバル変数に限らず、「○○はよくない」などと言われる物は絶対にダメという意味ではない。
○○以外の有効な手段があればそれを選べという意味であって、○○が有効となる限られたケースでは使っていい。
126:デフォルトの名無しさん
08/03/20 17:18:31
理由を理解せずに規約に従っても意味がない事の典型だな
127:デフォルトの名無しさん
08/03/20 18:31:27
>117
基本的にマクロは(特定の使い方以外)使わない方がいい。
マクロはプリプロセスで処理されてしまうため、コンパイルエラー時に酷い目に会う。
グローバル変数も使い方が難しいけど、コンパイラが識別できるものなのでマクロより余っ程マシ。
エラーが発生してもあくまで“変数”なので、マクロと違って識別名が普通に表示されるので
トレースしやすい。
因みに言うと、グローバル変数にするかどうかは「その値がどの範囲まで影響するか/正しいか」というのを
考えて決めるべき。プログラム中で一意な定数は積極的にconstグローバル変数にすべきだわな。
……しかし、こういう「疑問点を自ら追求する力を付ける」のがゆとり教育だったはずなんだけどね。
やっぱり失敗だったのか……
128:デフォルトの名無しさん
08/03/20 18:37:15
なんで勝手に117をゆとり教育を受けた人認定してるんだよ
129:デフォルトの名無しさん
08/03/20 18:41:28
エスパーするとC++でなく、Cの人が居ます。
「const リンケージ」でググって下さい。
>>117
C++で、それはただの定数で
変数のように書き換えることは出来ません。
グローバル変数が嫌われる主な理由は、
どこで書き換えられるか、把握し辛いことにあるため、
定数には当てはまりません。
130:デフォルトの名無しさん
08/03/20 18:56:40
どう見てもゆとりです、本当にありがとうございました。
131:デフォルトの名無しさん
08/03/20 20:02:06
1. マクロ定数はアドレスを完全に持たない。
(const 定数はアドレスを取得しようと思えばできるが、
アドレスを取得しさえしなければデータがデータメモリ上に置かれるとは限らない)
2. const 定数は名前空間に所属できる。
(マクロには名前空間がないため、名前被りが発生する可能性が大きい)
3. 値を求めるのに何らかの処理を伴う定数を使う場合、マクロだと毎回コードが埋め込まれてしまう。
(最適化が効く範囲ならいいのだが)
4. const 定数の方がコンパイルエラーが読みやすい。
(マクロの場合、置換後のテキストを元にしてエラーが出力されてしまう)
5. マクロの場合、型を明確に指定するには明示的なキャストが必要になる場合がある。
(見た目の問題でしかないと言われればそれまでだが)
6. ローカルスコープ内であっても、マクロ定数と同名の識別子を作ることはできない。
(作れない方がいいという意見もあるのかもしれないが)
7. const 定数を使うと副作用が一切無いことが明示される。
(キャスト演算子をオーバーロードしているクラスのオブジェクトの場合は例外だが)
132:デフォルトの名無しさん
08/03/21 11:21:21
質問があります。
動的配列を解放するときは要素数とかバイト数を指定しなくても
delete [] p;
でokですが、これはポインタpが指している動的配列の先頭バイトの
前に4byteの領域が確保されていて、ここに動的配列のバイトサイズ
が格納されているから、delete時にサイズを指定する必要がないと
聞いたことがあります。
しかし、動的配列の総バイト数はわかるとしても、要素のバイト数
の情報はどこに格納されているのでしょうか?
int *p; なら1要素のバイト数は4、double *p; なら1要素のバイト数は
8ですが、実行時にこの情報はどこから取得するのでしょうか?
ポインタpそのものは先頭1バイトのアドレス情報しか保持して
ませんから、こういう疑問をもった次第です。
133:デフォルトの名無しさん
08/03/21 11:30:24
ポインタそのものにそのアドレスに何が格納されてるかの情報は含まれてる。
そうでなければ cout << *p << endl; とかやったときに何が表示されるか未定義になってしまうじゃないか。
134:デフォルトの名無しさん
08/03/21 12:15:53
>ポインタそのものにそのアドレスに何が格納されてるかの情報は含まれてる。
ありがとうございます。
ポインタは、単に先頭バイトのアドレスを格納する4バイトの記憶
場所をもっているだけでなく、動的データ(または動的配列の要素)
のバイト数とか、データが文字なのか、整数なのか、実数なのか、
といった情報も裏側にもっている。これらの情報はポインタが指す
動的変数や動的配列側にではなく、ポインタ側にある。
という理解でよろしいでしょうか?
135:デフォルトの名無しさん
08/03/21 12:21:02
>>134
違う。ポインタの型によって静的に決まる
136:デフォルトの名無しさん
08/03/21 12:21:50
静的に型付けされてるからそんなものは要らない。
137:デフォルトの名無しさん
08/03/21 12:23:04
まさかvoid*をdeleteしてないよな…
あとポインタが4バイトとは限らないぞ。
138:デフォルトの名無しさん
08/03/21 12:30:09
うーん、わからなくなってきました。
文字型変数、整数型変数、実数型変数がコンパイル時に静的に
型付けされているのと同じというのは概念的にわかります。
しかし、自分が質問しているのは、その静的な型付けをどのよう
なしくみで実装しているのか?ということだろうと思います。
この段階にくると、コンパイラやアセンブラが理解できないと
無理なんでしょうけど。
139:デフォルトの名無しさん
08/03/21 12:50:07
実行時に要素のバイト数は、どこにも格納されてない。
と、考えて良い。
コンパイルする時点では、当然型が分かるので、それを使う。
この段階というか、かなり基礎。
※RTTIは上記が理解出来た上で。
140:デフォルトの名無しさん
08/03/21 12:59:28
>>138
いっぺん、自作クラスにoperator newとoperator deleteを実装してみればいいんじゃないかな。
乱暴な説明だけど、C++には「確保/削除するバイト数を受け取る、new/delete一族の大ボス的存在」である
::operator new(size_t)と::operator delete(void*, size_t)があって(他にも多重定義があるけど、とりあえず今はこの2例)、
たとえば int* p = new int; なんてのは、int* p = ::operator new(sizeof(int)); みたいにコンパイル時に解釈される。
同じく、後にdelete p; が出てきたら、pがint型のポインタなのはコンパイラにはわかるから(てか俺等にだってわかる)、
こっちは ::operator delete(p, sizeof(int)); になる。
141:デフォルトの名無しさん
08/03/21 13:24:09
>>138
>int* p = new int; なんてのは、int* p = ::operator new(sizeof(int));
int *p= new int [100]; は int *p=::operator new(sizeof(int)*100);
みたいになるんでしょうけど、要素のサイズが2バイトなのか4バイト
なのかの情報をコンパイル時にポインタに付加しておかないと、p[i]の
アクセスがうまくいかないのではないかと思うのですが、どうでしょうか?
142:デフォルトの名無しさん
08/03/21 13:25:59
>>141
p[i]のpの型はコンパイル時に分かってるんだから
143:デフォルトの名無しさん
08/03/21 13:44:43
まあ、強いて言えば、生成されたコード内に埋め込まれているって感じなのかな。
delete[] p;するときに、各要素のデストラクタを起動しなければならないわけだけど、
要素数は p = new T[count]; のcountで、実行時に変わる可能性のあるものだから、
ポインタの前かなんかに隠しておかなければならないわけ。
ちなみに、メモリブロックを単純に解放するだけなら要素数を隠しておく必要はないよ。
free()にサイズを指定しないでしょ?
メモリマネージャはメモリブロックの総バイト数をどこかに隠しておくかもしれないけど、それは別の話。
あとは、
T *p;
for(size_t i = 0; i < count; i++){
p->destruct();
++p; //←これ
}
これの++pがどうコンパイルされるかという、>>139が言うようにC言語レベルの基本的な話。
144:デフォルトの名無しさん
08/03/21 13:56:21
>>141
> p[i]のアクセス
たとえばintが4byteの環境だとすると、p[i] と書かれた箇所はネイティブコードにおいては
「pのアドレス+i*4byteのメモリアドレスへ行ってそこから先4byte分に書き込まれているビット配列を~」
という風に、既にintが「4byte」というミもフタも無い表現に変わっているから、型情報も何も関係無いよ。
145:デフォルトの名無しさん
08/03/21 14:27:51
>>141
p[i]というコードはコンパイルすると、アドレスはp+4*iといった意味の命令が生成される。
4が出てくる理由はpの宣言int* pによるもの(intが4byteの環境の場合)。
146:145
08/03/21 14:36:28
すまん、144と同じ事書いてしまった。
147:141
08/03/21 17:03:54
返事が遅くなってすみません。みなさん、ありがとうございます。
>>144 さんと >>145 さんの説明で
4byteという要素バイト数の情報をポインタp自体が保持して
いるのではなく、p[i]にアクセスする際にコンパイラがp+4*i
を計算する命令を生成しているだけ、ということがやっと理解
できました。
148:デフォルトの名無しさん
08/03/21 18:35:45
配列 new の場合、アップキャストは行わないから
配列のサイズは型から静的に決まる、と。
というか、アップキャストはできない。
そこが鍵だな。
149:デフォルトの名無しさん
08/03/21 18:36:13
×配列のサイズ
○要素のサイズ
150:デフォルトの名無しさん
08/03/21 18:44:36
C++ 的にはフォーマットの決まった string の中から数字を
読み出したりするにはどうするのがお薦めなのでしょうか?
例えば
string s("# foo 30 bar 0.1 xlajkdfl;ajkds");
から 30, 0.1 を抜く場合。
int n;
double x;
sscanf(s.c_str(),"# foo %d bar %lf",&n,&x);
としたりするのですが、もっと「本来」の方法はあるのでしょうか?
どうも workaround 的な気がするので。
151:デフォルトの名無しさん
08/03/21 18:48:30
atofで一つずつ進めて数値になる所を取り出す
152:デフォルトの名無しさん
08/03/21 18:51:36
それはないな
153:デフォルトの名無しさん
08/03/21 19:53:08
自分で字句解析器を書く。
154:デフォルトの名無しさん
08/03/21 20:00:28
各種正規表現ライブラリの後方参照を使う
155:デフォルトの名無しさん
08/03/21 20:29:16
>>150
そういうのが必要になる状況ってあまり無くない?
156:デフォルトの名無しさん
08/03/21 21:08:24
>>155
俺はソースコード解析したい時によくでる。
字句解析ライブラリもってこいって話だよな・・・
157:デフォルトの名無しさん
08/03/21 21:51:06
字句解析なら分かるんだけど、>>150は何か違う気がしたんで・・・
そうなら、分割の話から入るだろうし。
もしかして自然言語文からの抽出とかかな?
158:150
08/03/21 23:35:25
皆様どうもありがとうございました。私は結構こういう必要に出会います。
主にデータファイルをフォーマットし直したり、それを処理する場合です。
例えばデータフォーマットの情報などた先頭にあったりして、その情報を
元に解析したりする場合です。無視して決め打ちする事も可能な場合も多い
ですが、安全性のために整合性をチェックしています。
>>154 さんの方法が私には合っていると思います。普段 Ruby とかも使って
いて正規表現も使っているのに惰性で C 的にを使い続けてる自分の頭の堅さ
には呆れました。基本的に以下のようなコードで対応することを考えています。
まだあまり考えていないのでもう少しエレガントに書けるだろうとは思います。
string s("# foo 30 bar 0.1 xlajkdfl;ajkds");
boost::regex r0("^# foo ([0-9.]+) bar ([0-9.]+).+");
boost::match_results<std::string::const_iterator> mr;
if(boost::regex_match(s,mr,r0)){
const int n = boost::lexical_cast<int>(mr.str(1));
const double x = boost::lexical_cast<double>(mr.str(2));
cout << n<<"\t"<<x<<endl;
}
159:デフォルトの名無しさん
08/03/22 00:19:27
>主にデータファイルをフォーマットし直したり
それまさに字句解析の範疇な気がするけど・・・w
まぁ正規表現で簡単に済めばそれで良いと思うけどね。
160:デフォルトの名無しさん
08/03/22 12:44:30
>>159
> まぁ正規表現で簡単に済めばそれで良いと思うけどね。
regex ってかなり強力だと思う。テキストから情報拾う場合
に regex では簡単に通用しない場合ってどういうケース?
161:デフォルトの名無しさん
08/03/22 13:14:39
>>160
ネストした括弧の対応を取るとか
162:デフォルトの名無しさん
08/03/22 14:07:16
そこでboost::xpressiveですよ
163:デフォルトの名無しさん
08/03/22 14:15:50
boost もいろいろあってわからんなぁ。xpressive だと簡単なのかな。
俺だと char ごと読み取って '(' ')' を +1, -1 でカウントするとか
低レベルな事を考えちゃうけど。
164:デフォルトの名無しさん
08/03/22 14:52:00
通常の正規表現では任意のネストを表現することができない。
→xpressive ではパターンの自己再帰記述が可能。
→正規表現の枠を超える表現力を持つ(文脈自由文法)。
→xpressive だとネストの対応が可能。
165:デフォルトの名無しさん
08/03/22 15:01:28
boostの文字列処理ライブラリの事ならboost本のサンプルで読めたな
166:デフォルトの名無しさん
08/03/22 15:21:10
boost 本でお薦めってある? 本あまり出てないよね。
Karlsson の本は目を通したけど感じは判ってよいけど便利な本
という感じではない。秀和から出てる稲葉さんは本厚いし内容あるのかな。
167:デフォルトの名無しさん
08/03/22 17:31:22
inabaさんのは導入+軽いリファレンスにはいいかも
おおまかな概念と使用例が載ってる
boostもう使ってるよ~という人にはあまり必要ないかも
168:デフォルトの名無しさん
08/03/22 17:31:23
複数の派生クラスがそれぞれ値の異なるconst staticなメンバ変数をもっていて、
基底クラスへのポインタを使って読み取りたいのですが、どうすればいいでしょう
基底クラスへのポインタの配列に、いろいろな派生クラスを突っ込んでいる状態なので、
直接アクセスすることは出来ません
169:デフォルトの名無しさん
08/03/22 17:49:42
URLリンク(www.s-cradle.com)
170:デフォルトの名無しさん
08/03/22 17:54:12
>>166
C++ Template Metaprogramming
171:デフォルトの名無しさん
08/03/22 17:56:20
>>168
普通に仮想関数で
struct Base { virtual StaticMemberType GetStaticMember()=0; };
struct DerivedA : public Base {
StaticMemberType GetStaticMember { return DerivedA::staticMemember; }
};
あるいはRTTI使ってマルチメソッド。
172:171
08/03/22 17:59:13
ごめん引数1つのマルチメソッドはないなw
173:デフォルトの名無しさん
08/03/22 18:22:26
あー、関数をアクセサにすればよかったですね。何やってんだ俺
ありがとうございました
174:デフォルトの名無しさん
08/03/22 21:56:34
>>170
どうもありがとうございます。実はその本は持っていて次に読む予定。
しかし、これも洞察には優れているとは思うけど、便利な本では
ないかも。面白そうなんで期待してるけど。
175:デフォルトの名無しさん
08/03/22 22:03:15
>>174
面白くないよ。mplの単なるリファレンス。
176:デフォルトの名無しさん
08/03/23 00:53:31
DLLを読み込み、一部の機能のみを使った場合、
メモリの消費量はまるまるDLL分増えるのでしょうか
それとも使った機能の分だけ増えるのでしょうか
177:デフォルトの名無しさん
08/03/23 01:03:35
環境依存の話はスレチだけど、まるまる増えると思うよ。
178:デフォルトの名無しさん
08/03/23 01:12:30
仮想メモリはまるまる
物理メモリはコードについては使った分
データはシラネ
179:デフォルトの名無しさん
08/03/23 01:30:13
ありがとうございました
使いたいライブラリが8MBくらいあるもので、
まるまる増えるのはちょっとアレかな、と思って質問しました
改変可なので、必要な部分だけ取り出そうと思います
180:デフォルトの名無しさん
08/03/23 03:06:24
Managerクラスがあり
その機能は、一部のクラス(と言っても10個ぐらいある><)
にしか利用できないって設計の場合
一部のクラスをfriendする以外に何か方法はありませんか?
181:デフォルトの名無しさん
08/03/23 03:13:01
その一部のクラス以外はmanagerクラスのインスタンスを手に入れられないようにする。
182:デフォルトの名無しさん
08/03/23 09:41:11
>>180
freind じゃダメな理由を書いた方が答えが得られやすいと思う。
183:>>182
08/03/23 09:42:51
ミスった... orz
freind ⇒ friend
184:デフォルトの名無しさん
08/03/23 09:45:07
friend先に依存が出来るからじゃね?
普通、friendは最終手段だし
185:デフォルトの名無しさん
08/03/23 12:07:26
そんなことはない。
186:>>182
08/03/23 13:05:05
friend 先に依存って何?
187:デフォルトの名無しさん
08/03/23 13:58:48
一部のクラスだけ特別扱いするというのがManagerクラスの仕様なら、
friendによる依存は妥当だと思う。
188:デフォルトの名無しさん
08/03/23 14:45:51
一部のクラスの基底クラスとして
Manager を取得するクラスを作って、
その1つだけを friend にすれば?
189:180
08/03/23 14:58:22
friendが結構な数になってしまうんです。
下手すれば私のリアルfriendより多いぐらい
それが悔しくて
190:デフォルトの名無しさん
08/03/23 14:59:16
誰が上手い事を言えと
191:184
08/03/23 15:01:24
俺は181に一票で
192:デフォルトの名無しさん
08/03/23 15:02:43
その方法を聞いてるんだろw
193:デフォルトの名無しさん
08/03/23 15:09:28
パスワード掛ければいいんじゃないですかね
194:デフォルトの名無しさん
08/03/23 15:14:48
w
195:デフォルトの名無しさん
08/03/23 15:25:03
権限プログラミングってのも面白そうじゃないか
196:デフォルトの名無しさん
08/03/23 15:42:23
singletonなら簡単なのにな
197:デフォルトの名無しさん
08/03/23 16:01:39
思い出したw
____
|← reject| boostの中の人 singleton ユーザー
. ̄.|| ̄ ̄ ┗(^o^ )┳(`Д´)┳(^o^ )┛≡=-
|| ┏┗ ┗┗ ┏┗ ≡=-
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
198:デフォルトの名無しさん
08/03/23 16:06:07
ユーザーは欲してると思うが
199:デフォルトの名無しさん
08/03/23 16:34:52
にわかに得た知識で面白いこと考えた!
Managerのインスタンスを受け取る関数の引数に関数オブジェクトを使って
内部で一定のアルゴリズムで正しい値を返すもの(パスワードの暗号化みたいな)にのみそのインスタンスを渡してやる風にすればいいんじゃね?
更にインスタンスを受け取る関数をテンプレート化してやり、欲しい権限までのクラス型インスタンスを返すようにしてやればアクセス制限も出来て完璧!
とここまで考えてわざわざこんなことしてもオーバーヘッドが大きいだけなことに気づいた
そもそも何の意味があるんだっけか
200:デフォルトの名無しさん
08/03/23 16:45:12
だから >>188 でいいだろ、別に。
201:デフォルトの名無しさん
08/03/23 16:57:35
Managerクラスコンストラクタなどをprotectedにして、使うクラスはManagerを継承する。
202:デフォルトの名無しさん
08/03/23 17:02:41
>>188 >>199 >>201
これらの方法は、Managerクラスの許可なく好き勝手に権限のあるクラスを作れる。
そういうのを>>180は制限したいんじゃないの?
203:>>182
08/03/23 17:08:28
>>201
そう言うのは最悪。
あとから見て、継承が本当に必要だったのか、単に特定のメソッドを
使わせるために継承しているのかがわからなくなるから。
204:201
08/03/23 17:21:39
>>203
意味がよく分からないけど、、、「特定にメソッドを使わせるために継承が必要かどうかがわからなくなる」ってこと?
そんなこと言ってたら何もできない。
friendだったら、なぜfriendにしたか分からなくならないの?
friend よりいいと思うけどな。
friend じゃprivateのメンバにアクセスできてしまう。
Managerクラスを機能を利用するんだから、継承しかないでしょ。
使う側のクラスに持たせるとなると、コンストラクタとかはpublicになってしまうし。
205:デフォルトの名無しさん
08/03/23 17:40:32
継承すると
Managerの中のstaticでない変数とか勝手に作られない?
206:デフォルトの名無しさん
08/03/23 17:41:03
>>203
Manager クラスじゃなくて単に許可コントロール用の class を作る
というのは有りじゃない?そういう例をまともな本で見た記憶がある。
207:デフォルトの名無しさん
08/03/23 17:42:27
-カーズは-
2度と地球へは戻れなかった…。
鉱物と生物の中間の生命体となり
永遠に宇宙空間をさまようのだ。
そして死にたいと思っても死ねないので
―そのうちカーズは考えるのをやめた。
全部globalにすればいいじゃん
208:デフォルトの名無しさん
08/03/23 17:44:01
>>206
電波の缶詰の人のサンプルもそうだった
ライブラリ的なものを
外部からいじられないようにするためだったら
そんな感じでもいいんじゃまいか
村八分
209:デフォルトの名無しさん
08/03/23 17:47:19
Managerインスタンスを受け取るために、Managerにコールバックしてもらえばいいんじゃない?
class FriendClassA; // 前方宣言
class FriendClassB;
class Manager
{
public:
class Friend { public: virtual void authorize(Manager* m) = 0; };
void getInstance(Friend* p)
{
if( dynamic_cast<FriendClassA*>(p) ||
dynamic_cast<FriendClassB*>(p) ||
/* 権限のあるクラスかをチェック */ )
{
p->authorize(this);
}
}
};
210:デフォルトの名無しさん
08/03/23 18:25:34
それは、インスタンス取るのに時間かかるし
friendでいいじゃんって話になるも
211:デフォルトの名無しさん
08/03/23 18:40:51
速度が重要ならtemplate部分特殊化とかで。
class Manager
{
public:
template <class Unauthorized>
static void authorizedProc(unauthorizedClass * p)
{ std::cout << "not authorized" << std::endl; }
template <>
static void authorizedProc(authorizedClassA * p)
{ p->Proc(m_instance); }
// 以下許可するクラス分同じコード
private:
Manager m_instance;
};
冗長だし検証してないけど。
212:デフォルトの名無しさん
08/03/23 18:45:30
Manager を使えるクラスを作成する場合には
ファクトリクラスを通すようにする。
で、そのファクトリクラスを friend にして、
そこで Manager クラスを取得して、
各クラスにそれを渡すようにする。
設定関数は各クラスの共通基底クラスに作って、
それをファクトリクラスの friend にする。
213:デフォルトの名無しさん
08/03/23 18:46:54
先輩から聞いたのですが、extern "C" {}せずに構造体を宣言すると、
余計なクラス情報がくっつくって本当ですか?
214:デフォルトの名無しさん
08/03/23 18:52:41
そんなことは聞いた事が無いが、
特定のコンパイラでそういう事があるとかいうんだったら俺は知らない。
215:デフォルトの名無しさん
08/03/23 18:55:11
クラス情報って具体的には何なんだ?
216:デフォルトの名無しさん
08/03/23 18:57:34
>>213
マングリング名にクラス情報がくっつくって話だと思う。
217:デフォルトの名無しさん
08/03/23 18:59:55
>>214-216
言ってたのはシリコンバレー帰りの先輩です
純粋なCの構造体にするにはやはりextern "C"が必要なのですね。
ありがとうございました。
218:デフォルトの名無しさん
08/03/23 19:00:36
>>217
どこからそういう判断をしたんだ?w
219:デフォルトの名無しさん
08/03/23 19:01:52
構造体にextern "C"は関係無いだろ
220:デフォルトの名無しさん
08/03/23 19:02:10
>>216
構造体名って C でそもそも何らかのマングリングされるの?
221:デフォルトの名無しさん
08/03/23 19:07:59
C++なら名前空間やらなんやらくっつくだろ。
222:デフォルトの名無しさん
08/03/23 19:10:41
C で付かないなら
純粋な C の構造体かどうかなんて
どう区別するんだろうか。
223:>>182
08/03/23 19:46:38
>>204
まじめな話、もう一度継承についてちゃんと勉強した方がいいと思う。
(>>205 の内容を理解できてる?)
継承はアクセス制限のためにあるものじゃない。
極端な話、全てが public であったとしても、継承は有用。
これに対して、friend は純粋にアクセス制限を回避するもので、かつ
アクセス制限を回避する以外の機能は無いから、なぜ friend にしたか
がわからなくなることはない。
(もちろん、なせアクセス制限を回避する必要があるかはどっかに書いて
おく必要があるだろうけど。)
>>206
それならアリだと思う。
224:201
08/03/23 19:54:02
>>223
>>205
作られるけど。外から参照されたくないものはpublicにしなけらばいいじゃん
225:201
08/03/23 20:00:37
>>223
>継承はアクセス制限のためにあるものじゃない。
>極端な話、全てが public であったとしても、継承は有用。
だから、継承が駄目なんですか?
継承は色んな意味で使えて「わかりにくい」から駄目ってこと?
226:デフォルトの名無しさん
08/03/23 20:00:37
何かもう駄目だなここって思ったの俺だけだろうか
227:デフォルトの名無しさん
08/03/23 20:02:29
Manager 使ってる部分を別プロジェクトにする。
あとは各クラスのオブジェクト生成を外部から隠せばいい。
228:>>182
08/03/23 21:01:54
>>224
> 作られるけど。外から参照されたくないものはpublicにしなけらばいいじゃん
おいおい、ほんとにもう少し勉強してからこいよ。
引っ込みつかなくなってるだけならいいけど、マジでそう思ってるとしたら
ちょっとまずいよ。
まずい理由の一つは、private でもその変数が見えなくなるわけじゃない、
アクセスできなくなるだけだから。
この違いわかってる?
>>225
> 継承は色んな意味で使えて「わかりにくい」から駄目ってこと?
>>203 に書いたのはそう言うこと。
それしか方法が無いならしょうがないけど、friend と言うもっといい方法があ
るのにわざわざ使わないのは、別の意図があるようにとられる危険性が高い。
229:201
08/03/23 21:17:23
>>228
>マジでそう思ってるとしたらちょっとまずいよ。
Managerを継承していないクラスから参照されたくない場合はpublicにすれば良いって事だよ?
>まずい理由の一つは、private でもその変数が見えなくなるわけじゃない、
>アクセスできなくなるだけだから。
「見える」→メンバ変数の値が取得できる。(getter)
「アクセス」→メンバ変数の値が書きかえれる。(setter)
って意味で言ってるのなら
getter、setter定義してやれば、当然見えるしアクセスも可能。
230:デフォルトの名無しさん
08/03/23 21:42:53
もしかして201氏は、
Managerは1つのクライアント(Managerを使うクラスオブジェクト)の管理のみ引き受けるもので、
クライアントと同数のManagerオブジェクトが必要と考えているのではないだろうか。
231:>>182
08/03/23 22:07:14
>>229
> 「見える」→メンバ変数の値が取得できる。(getter)
> 「アクセス」→メンバ変数の値が書きかえれる。(setter)
ほら、全然理解できてない。
簡単な例でいうと、
int a, b;
class X {
private: int a;
};
class Y: public X {
int foo(){ return a; }
int bar(){ return b; }
};
ってやると、foo() の中で X::a をアクセスしようとするからエラーになるよね。
もし、C++ の private が変数を「見えなくする」なら bar() の b と同じように、
foo() は ::a を返すはずだろ?
これが、「見えなくなること」と「アクセスできなくなること」の違いなわけ。
これによる、影響は自分で調べてみてね。
>>230
まあ、それはそれでそれこそもっとよく考えろとしか言えないわけだが...
232:デフォルトの名無しさん
08/03/23 22:11:42
何でこんな残念なスレになってしまったんだ。
233:デフォルトの名無しさん
08/03/23 22:12:43
だって にちゃん だもの
234:デフォルトの名無しさん
08/03/23 22:56:01
VSyncの話したらひどいことになりそう
235:デフォルトの名無しさん
08/03/23 22:57:56
>>231
初心者スレでやれ
ウザイ
236:デフォルトの名無しさん
08/03/23 23:03:27
結局>>182って文句言ってるだけで答えて無いじゃん
237:>>182
08/03/23 23:14:58
答えは >>188 で既にでてるだろ。
まあ、10個ぐらいなら全部 friend 宣言してもいいと思うけど。
もしかして君も >>201 みたいに理解できてないやつなの? (w
238:デフォルトの名無しさん
08/03/23 23:32:29
>>188だとManager::getInstanceみたいなので取得するのと大差無いと思うが・・・
まぁ、それはともかく、>>180にfriendなどを使ってまで
制限する必要性があるのか、疑問だな。
クラスごと使わせなくするとこにfriendを使用している時点でおかしいと思う。
無名名前空間やdetails名前空間で十分なんじゃないか?
239:201
08/03/23 23:44:18
>>231
>foo() の中で X::a をアクセスしようとするからエラーになるよね。
アクセッサをManagerの方に定義することを考えていたんだけどな。
「見える」「見えない」の話じゃんくてprivateだからだろ。
>もし、C++ の private が変数を「見えなくする」なら bar() の b と同じように、
foo() は ::a を返すはずだろ?
グローバル変数よりメンバ変数を参照しにいくのは知ってます。
Managerの方に「一部のクラス」に使わせたい機能だけ、protected または public にして
一部のクラスがManagerを継承すればいい。
Manager のprivateのメンバには「一部のクラス」も参照できない。
「一部のクラス」以外にManagerクラスのインスタンスを作られるのが困る場合は
コンストラクタなどをprotectedにすればいいんでは?
「一部のクラス」に対してManagerは一つらしいので、また違ってきますが・・・・
240:デフォルトの名無しさん
08/03/23 23:58:52
これで friend いらない
-- friends.cpp
#include "A.h"
#include "B.h"
namespace
{
class Manager {};
Manger& manager();
}
void A::f() { manager().a(); }
void B::g() { manager().b(); }
241:>>182
08/03/24 00:06:26
>>238
> まぁ、それはともかく、>>180にfriendなどを使ってまで
> 制限する必要性があるのか、疑問だな。
それは、>>180 に聞いてもらわないとダメだけど、そう言う状況はありえると思うよ。
例えば、デバッグのためにマネージャの状態を直接見たりいじったりするクラスとか。
ただ 10個もあるのは、ちょっと多すぎるような気はするけどね。
>>239
頼むから、もう少し勉強してからレスしてくれ。
全然俺の言ってることが理解できてないよ。
242:デフォルトの名無しさん
08/03/24 00:08:40
で、アホなのはどっちなの?初心者なのでよく分かりません
243:デフォルトの名無しさん
08/03/24 00:51:50
>>242
やり方は色々ある。って話に落ち着けていいんじゃないのw
メイヤーズもそんなことeffective c++に書いてたでしょ。
244:デフォルトの名無しさん
08/03/24 05:56:56
>>242
「そいつの中にあるもの」の質はともかく、
「そいつの中にあるものを説明する能力」はどっこいどっこいです。
245:デフォルトの名無しさん
08/03/24 17:47:39
仮想関数を持たないクラスXとクラスYがあります。
YはXを継承しています。これらのクラスに対応する
インターフェイスのクラスIXとIYを以下のように定義しました。
しかし、コンパイルエラーでした。クラスYは抽象クラス
とみなされたようです。でも、クラスYはf()の定義も
g()の定義も持っているので抽象クラスではないように思えます。
XとYのインターフェイスを作る方法を教えて下さい。
class IX {
virtual void f() = 0;
};
class X : public IX {
void f() {}
};
class IY : public IX {
virtual void g() = 0;
};
class Y : public X, public IY {
void g() {}
};
int main()
{
Y y; // エラー(抽象クラスあるいは構造体のオブジェクトが宣言されています)
return 0;
}
246:デフォルトの名無しさん
08/03/24 17:54:22
IX IX
↑ ↑
X IY
↑↑
Y
という継承木になっている。
X::IX::f は定義されているが、
IY::IX::f は定義されていない。
インタフェースクラスを作るなら、IX を仮想継承する必要がある。
ただ、それでも Y で f を定義する必要がある。
あと、インタフェースクラスに限らず、基底クラスには
必ず仮想デストラクタを定義するのを忘れないように。
247:デフォルトの名無しさん
08/03/24 18:14:09
>>246
ありがとうございます。
以下のように変更したらエラーが警告になりました。
この警告は無視していいような気がします。
>あと、インタフェースクラスに限らず、基底クラスには
>必ず仮想デストラクタを定義するのを忘れないように。
OKです。
class IX {
virtual void f() = 0;
};
class X : virtual public IX {
void f() {}
};
class IY : virtual public IX {
virtual void g() = 0;
};
class Y : public X, public IY {
void g() {}
};
int main()
{
Y y; // 警告('Y' : 2 つ以上のメンバが同じ名前を持っています。'X::f' から継承します。)
return 0;
}
248:デフォルトの名無しさん
08/03/24 18:50:40
Y::f では X::f と IY::f のどっちの実装を使えばいいのか分からないというもの。
まあ、今回の場合は IY::f に実装がないから X::f を使いますよという警告だけど、
Y に void f() { X::f(); } と書いておくのが無難。
249:デフォルトの名無しさん
08/03/24 19:06:35
class T
{
T( int );
}
を
T *T_array = new T [100];
は出来ないじゃん?
#placement new使えってのはなしで。
std::vectorはどうやってこういうコンストラクタが引数を持ってるクラスを受け入れてるの?
250:デフォルトの名無しさん
08/03/24 19:07:20
placement newで
251:デフォルトの名無しさん
08/03/24 19:11:33
>>248
上の例では void f() 1個だけですが、実際のIXは純粋仮想関数を
22個もっています。Yに22個の関数をわざわざ定義するのはなんだか
無駄な気がするのですが。。。
252:デフォルトの名無しさん
08/03/24 19:18:29
>>251
まあ、面倒なら今のところは無視してもいいかもしれない。
コメントでも書いとこう。
253:デフォルトの名無しさん
08/03/24 19:26:44
>>241
頼むから、もう少しまともな説明してくれ。
254:デフォルトの名無しさん
08/03/24 19:31:33
>>252
わかりました。ありがとうございました。
255:デフォルトの名無しさん
08/03/24 19:31:46
friend 使うと「一部のクラス」が増えるとManagerも弄らないと駄目だな。
256:デフォルトの名無しさん
08/03/24 19:34:11
拡張性を敢えて犠牲にするなら、個別に friend するしかない。
拡張性もある程度考慮するなら基底クラス作ってそれだけ friend 。
あとは本人がどうしたいか、だな。
257:デフォルトの名無しさん
08/03/24 20:12:41
>>253
非常に初歩的な内容だし、あの説明で理解できないなら、
もうあきらめた方がいいぞ。
258:デフォルトの名無しさん
08/03/24 22:58:50
IDすら出ない板で煽り煽られ大変ですな
259:180
08/03/24 23:04:33
私の為に喧嘩しないで><。
260:デフォルトの名無しさん
08/03/24 23:59:31
struct B{
struct P{ B *temp; }
B( P p ){ swap( *this, *(p.temp) ); }
operator P (){ P p; p.temp = this; return p; }
};
B Return(){ return B(); }
void Accept( B &b ){};
------------
Accept( Return() ); //Error
俺、何間違えてるの?
261:デフォルトの名無しさん
08/03/25 00:06:50
設計?
262:デフォルトの名無しさん
08/03/25 00:07:13
エラーメッセージはキチンと書く
263:デフォルトの名無しさん
08/03/25 00:09:50
;
264:デフォルトの名無しさん
08/03/25 00:11:00
質問の仕方
265:デフォルトの名無しさん
08/03/25 00:11:54
>>263
266:デフォルトの名無しさん
08/03/25 00:11:55
Bにデフォルトコンストラクタないからとか?
267:デフォルトの名無しさん
08/03/25 01:12:43
Humanクラスを基底クラスとするTanakaやAsouやIshikawaクラスがあるとします
Humanは抽象クラスとして用いるつもりです
このときHumanにあるstaticメソッドを一回だけ呼び出したいときってどうすればいいでしょうか?
Humanのコンストラクタで呼び出したとすると、TanakaやAsouのコンストラクタでも呼び出されますよね
static bool initのような変数をフラグとして使う方法は思いついたのですが、
もっとスマートな方法はないのでしょうか?
268:デフォルトの名無しさん
08/03/25 01:16:38
シングルトンやそれに関わるC++の実装は非常に面倒くさくて
自分で一からやろうと思うとどうしても乱雑になる。
マルチスレッドが入ってくるともっと面倒くさくなる。
269:デフォルトの名無しさん
08/03/25 01:25:21
>>260
人生、かな?
270:デフォルトの名無しさん
08/03/25 01:49:26
>>267
そのメソッドを呼び出したいのは、Human派生のオブジェクトを生成したタイミングなの?
271:267
08/03/25 02:13:35
>>270
そうですね
Human派生のオブジェクトを生成する前に呼び出しても構わないのですが
272:デフォルトの名無しさん
08/03/25 02:30:23
>>271
であれば、全てが始まる前に自分で一度だけ呼ぶのが良いと思うな。
273:デフォルトの名無しさん
08/03/25 02:31:52
>>272
それはstaticな変数をフラグにするよりダメじゃねぇかw
274:267
08/03/25 02:39:11
>>272
あぁそうか、そもそもstaticなメソッドなわけだから
int main(){
Human::onlyOnceCalled()
みたいなかんじで
最初の方で適当に呼んでおくってのもありかもしれませんね
一回だけしか呼ばないって保証がないような気もしますが
275:デフォルトの名無しさん
08/03/25 02:49:38
>>274
必ず最初に読んでしまってよいなら、クラスにスタティックなメンバを定義して
それの初期化の中で実行させてみては?
// human.h
class Human() {
// 中略
class Initializer { Initializer() { onlyOnceCalled(); } };
static Initializer init;
};
// human.cpp
Human::Initializer Human::init;
文法間違ってたらすまん
276:275
08/03/25 02:51:47
Human::Initializerのコンストラクタがpublicになってないとか、いろいろダメだorz
そこは適当におぎなって
277:267
08/03/25 03:01:51
>>275
なるほど。こういう方法もあるんですね
勉強になりました
ありがとうございました
278:デフォルトの名無しさん
08/03/25 03:05:20
保証が欲しかったのか。失礼。
initialization orderを気にするならこんな感じかな。
class Human() {
class Initializer {
Initializer() { onlyOnceCalled(); }
public:
static void Initialize() { static Initializer instance; }
};
};
これで、Initializer::Initializeを呼んだタイミングで一度だけ初期化されるようになるよ。ただしこの場合は複数スレッドとかが動き出す前に呼んでね。
279:260
08/03/25 09:32:50
ぇ?コンパイル通る?
gccだと通らないんだけど・・・
280:デフォルトの名無しさん
08/03/25 09:53:30
>>279
どこを見てそう思うんだよ・・・
指摘してくれてるだろ
>>263
>>266
あとAcceptがReturnの返す一時オブジェクトを参照してるから何とかしよう
281:デフォルトの名無しさん
08/03/25 11:14:49
>>279
まずは省略や手抜きをせずに、Bの定義を全部書け。
そして何をしたいのかはっきりさせろ。
282:260
08/03/25 16:02:29
いや、やりたいことは下のやつを知りたかっただけ。
URLリンク(ja.wikibooks.org)(Move_Constructor)
に書いてあることってnon-const referenceを受けるべきとろこに一時オブジェクトを渡せるって話だと思って、
渡してみたらコンパイラ通らないどーん。な状況。
283:デフォルトの名無しさん
08/03/25 16:44:42
>>282
これで通った
struct B{
struct P{ B *temp; };
B(){}
B(P p){ swap( *this, *(p.temp) ); }
operator P () { P p; p.temp = this; return p; }
};
B Return(){ return B(); }
void Accept( B b ){};
int main(){ Accept( Return() ); }
284:デフォルトの名無しさん
08/03/25 17:14:20
参照渡しから値渡しに変更した理由が分からん
285:デフォルトの名無しさん
08/03/25 17:18:44
抽象クラスのメソッドの定義で質問があります
抽象クラスにおいて、自分自身のクラスへのポインタの引数を取るメソッドは不可能なのでしょうか?
たとえばこういうコードです
class Human {
void foo(Human *human) = 0;
};
コンパイルエラーになってしまいますが、なぜそうなるのか分かりません
抽象クラスだから、インスタンスを作れないので
void (Human human);
のようなメソッドはだめですよね、でもポインタならいけると思うのですが
286:デフォルトの名無しさん
08/03/25 17:20:52
B::operator P()の戻り値から構築されるBの一時オブジェクトは非const参照のAccept(B&)では受け取れないんじゃ?
287:デフォルトの名無しさん
08/03/25 17:23:26
その発送は無かったわ、thisポインタというものが(ry
virtual書いてみたらどうかな?
288:デフォルトの名無しさん
08/03/25 17:27:02
一時変数を値渡しする理由は?const参照にしない理由が分からない。
289:285
08/03/25 17:32:20
>>287
すいません元のコードではvirtualをつけてました
thisポインタは分かるのですが、この抽象クラスを継承したクラスの間でやりとりしたいことがあるのです
不勉強なので間違ってるかもしれませんが、「関連」というのをやりたいのです。
>>285の例でやるなら、一般的にはHumanクラスにHuman *hoge;みたいなポインタをメンバに持たせて関連付けするそうですが
関数の引数でやれないかと思いまして
290:デフォルトの名無しさん
08/03/25 17:35:09
>>288
const参照でもいいかもしれないけど、それ以上所有権を動かせなくならない?
291:デフォルトの名無しさん
08/03/25 17:45:20
Acceptに入ってからも譲渡するなら、
void Accept(B& b) {}
B b = Return();
Accept(b);
の方が良くないかな、それ以前に何のためのPなんだ?
292:デフォルトの名無しさん
08/03/25 17:47:47
>>285
どういう一般的例なのかちょっと分からないけど、
処理と情報を分ける実装の方が個人的にはスッキリするかな
んで、そのプログラムvirtualつけてエラーが出る理由が分からないんだけど…
293:デフォルトの名無しさん
08/03/25 17:49:24
あぁ、失礼した、operator Pはconst守るようにしてるのね
ごめん、俺が悪かった
294:292
08/03/25 18:06:34
>>292
すいませんすごく単純なクラスを作り直し、実験してみると、エラーはでませんでした。
「抽象クラスをインスタンス化することができません」というエラーメッセージだったので、
質問させていただいたのですが、おそらく他のところにエラー.の原因があると思うのでもう一度見直してみます
295:294
08/03/25 18:09:51
>>294の名前欄は>>285の間違いです
296:デフォルトの名無しさん
08/03/25 19:45:31
auto_ptrはauto_ptr_refクラスを介して対処している。
もう知っているかもしれないけど、
C++0xでは非const参照でも一時オブジェクトを受けられるようになる(右辺値参照)。
297:デフォルトの名無しさん
08/03/25 22:07:18
move semantics と rvalue reference &&
298:デフォルトの名無しさん
08/03/25 22:23:46
右辺値参照は何度もこのスレでも話されてるけど理解できん。
299:デフォルトの名無しさん
08/03/25 22:33:41
エラー出る出る言うなら、同じエラーが出る小さいプログラムを示せよ。
BやらPやらの例も、そもそもswapがないでコンパイル止まるしな。
300:デフォルトの名無しさん
08/03/25 22:34:02
右辺値及び左辺値(この二つは組)、参照の理解を固めてから見直すとよろし
301:デフォルトの名無しさん
08/03/25 22:45:08
>>298
簡単に言うと「swapでおk」ってこと。
302:260
08/03/25 23:08:35
おなにーでさーせん。swapとかごめん。あと別に必要なかったかも。
コンパイル通った。
>>283と一緒かな?
class D {
public:
struct Proxy { Proxy( D *d ):d_( d ){}; D *d_; };
operator struct Proxy () { return Proxy( this ); };
D( struct Proxy p ) {};
void operator = ( struct Proxy p ){};
D(){};
D( D &rhs ){};
void operator = ( D &rhs ){};
};
D Return() { return D(); }
int main( int, char** ){
D d = R();
return 0;
}
Accept( D &d );ってのは間違ってたかも。
ようは、
D( const D &rhs )だと、オーナーシップの移譲とかでrhsに変更加えられない。で、
D( D &rhs )だと、右辺値を渡せない。
だから、Proxyを返して、ごにょごにょする。って話なのか。
303:デフォルトの名無しさん
08/03/27 00:31:14
Cの関数ポインタにC++のClassの実体化した関数ていれられますか?
ビルドエラーが出るんですけど、そもそもそんなの出来ない?
304:デフォルトの名無しさん
08/03/27 00:54:49
>>303
できない。
関数ポインタとメンバ関数ポインタは別物。
305:デフォルトの名無しさん
08/03/27 01:38:47
>>303
Windowsのコールバック関数みたいに
こっちから引数を渡せれば、どうにでもできる。
306:デフォルトの名無しさん
08/03/27 01:54:41
>>303
sizeofを使ってポインタサイズを調べてみると、あれびっくりサイズがデカイって分るよ。
どうやっても入りません、キャストしたら情報ロストします。
307:デフォルトの名無しさん
08/03/27 02:00:59
>>306
いろいろ勘違いしてるような。
308:デフォルトの名無しさん
08/03/27 02:24:05
>>307
どこを?
具体的にどうぞ。
309:デフォルトの名無しさん
08/03/27 02:29:53
>>304-306 のうち確実に間違っているのは >>305 です、要注意。
310:デフォルトの名無しさん
08/03/27 02:49:53
面倒だからboost::functionを調べてみ >303
311:デフォルトの名無しさん
08/03/27 02:56:20
詳しく説明した方がいいかと
要するに、メンバ関数ポインタがさす関数はvirtualである事もあって
インスタンスに仕込まれた仮想テーブルを参照して、関数テーブルのうちどの位置にあるものかを取得する必要がある。
また、関数はvirtualでないケースもある、この場合仮想テーブルには関数のアドレス情報はないので、関数メンバポインタ内に情報がなければならない。
関数メンバポインタはこれら複合情報で構成された構造体となっている。
312:デフォルトの名無しさん
08/03/27 03:03:53
どこが詳しいのか
313:デフォルトの名無しさん
08/03/27 06:03:12
それなりに詳しいと思うけど、
であるがゆえに「要するに」から始まっているのは間違いだと思う。
314:デフォルトの名無しさん
08/03/27 07:26:14
>>303
関数ポインタには入れられないが、
実体とメンバ関数ポインタの対を構造体にしたものを引数に取る
ラッパ関数を通して呼ぶことはできる。
もちろん、C 側ではその構造体を直接扱うことはできないから、
void * を通すなり不完全型を利用してポインタで扱うなりする必要はあるけど。
315:デフォルトの名無しさん
08/03/27 07:39:53
>>309
>>305はCのライブラリのコールバック使うときとかの対処法の話じゃね?
大抵はvoid*のパラメータ持ってるし。
316:デフォルトの名無しさん
08/03/27 07:46:12
virtual関係無いよね。
317:デフォルトの名無しさん
08/03/27 08:15:45
そもそも、C++のclassの実体化した関数って何?実体化って何を言ってるんだ
インスタンス増えたら関数も増えるとか思ってるのだろうか、理解に苦しむ
URLリンク(www.microsoft.com)
318:303
08/03/27 08:50:26
やりたいのは複数newしたクラスからCの関数叩くんですけどその時の引数にコールバック用のCの関数ポインタがあるんです
そしてその時呼んだ実体に関数ポインタによって帰ってくるようにしたいんです
319:デフォルトの名無しさん
08/03/27 09:03:26
引数を加えて、static関数で良いんじゃ?
320:デフォルトの名無しさん
08/03/27 09:20:50
>>317
非staticメンバ関数/インスタンスメソッドの事だとみんな理解してるよ。
>>318
コールバック関数のパラメタを汎用ポインタとかで指定できるなら、そこにオブジェクトのアドレスを入れて、コールバック関数内でキャストしてメンバ関数を呼ぶ。
パラメタを指定できないなら、コールバック関数から見えるスコープの変数にオブジェクトのアドレスを入れておき、コールバック関数からメンバ関数を呼ぶ。
321:デフォルトの名無しさん
08/03/27 10:10:15
クラスの関数ポインタはthisが略されてるようなもんじゃね
322:デフォルトの名無しさん
08/03/27 10:31:11
>>317
往生際が悪い、素直に自分の知識不足でしたと認めろ
323:デフォルトの名無しさん
08/03/27 11:13:55
>>317
そのあたりは処理系依存だろ
324:デフォルトの名無しさん
08/03/27 13:09:21
static メンバ関数を C のコールバックに登録するのってよく見るし実際に
やったこともあるんだけど、ほんとは extern "C" と extern "C++" の違いで
型が遭わないはずなんだよね。
だからって対応策がわかんないし、使ったことのあるコンパイラでは全部通るから
そのまま使っちゃうんだけどさ。
325:デフォルトの名無しさん
08/03/27 13:35:22
>extern "C" と extern "C++"
"C" とかの修飾は、識別子を外部にどういう規則で公開するかという点についての指定であって、スタックフレームの作り方の指定ではない。
機種依存なので、そっちにいけと事になるが、cdeclとpascalが違えば "C" を付加しても動作しない。
C型のスタックフレームを持つ関数として登録可能な関数なら、C型のコールバックに登録する事ができるという事。
そうでないなら、コンパイルが通ったとしてもうまくいかない。
326:デフォルトの名無しさん
08/03/27 13:52:21
>>325
スタックフレームとか実装に立ち入った話はしてない。言語概念上の型が違うんだよ。
327:デフォルトの名無しさん
08/03/27 13:53:59
>>326
力いっぱいデタラメぶちかまさない
328:デフォルトの名無しさん
08/03/27 13:58:42
知識不足は許容できるが嘘吐きになってはイカンぜよ
329:デフォルトの名無しさん
08/03/27 14:03:56
>>327-328
気持ちはわかる。きっとみんなこれらは同じものとして使ってるだろうし、
動作も問題ないだろうさ。
でも規格ではエラーにならないとダメなんだよ。はっきり書いてあるから。
7.5 "Linkage specifications" p1 より
> ... Two function types with different language linkages are distinct types even
> if they are otherwise identical.
gcc でもバグ扱いだ。
URLリンク(gcc.gnu.org)
330:デフォルトの名無しさん
08/03/27 14:06:37
>>329
自分を嘘と虚栄で塗り固めるような真似はやめた方がいい、どこに突っ込み入っているのかすら理解できていないだろ。
331:デフォルトの名無しさん
08/03/27 14:10:44
静的メンバ関数はextern "C++"ではない
332:デフォルトの名無しさん
08/03/27 14:11:10
328は327に宛てたもんだと俺は思った、どうでもいいけど。
333:329
08/03/27 14:11:40
>>330
ごめん。どこに突っ込み入っているのかすら理解できてない。
どこが嘘になってるの?
334:デフォルトの名無しさん
08/03/27 14:16:32
>>331
何を根拠にそんなこと言うのか知らないけど、じゃぁ静的メンバ関数の
language linkage は "C++" 以外の何になるのさ?
335:デフォルトの名無しさん
08/03/27 16:56:26
虚言癖というか妄想癖というか・・・なんかもう病気だね(汗
336:デフォルトの名無しさん
08/03/27 17:04:34
>>334
静的メンバ関数のリンケージは内部リンケージで
その根拠は外部に公開されないから
逆にextern "C++"と同じという根拠は?
337:デフォルトの名無しさん
08/03/27 17:05:02
もうv(^・^)vの人はいないの?
338:デフォルトの名無しさん
08/03/27 17:20:53
ちゃんと勉強しろ、そんな高度な話題じゃねぇよ
339:デフォルトの名無しさん
08/03/27 18:55:41
コンストラクタの中で
配列宣言しているオブジェクトの
コンストラクタ引数を設定するにはどうしたらいいですか?
340:デフォルトの名無しさん
08/03/27 19:03:37
class Test{
Test0 objects[10];
...
};
Test::Test()
:objects[0]( 10 )
,objects[1]( 8 )
...
{
}
こんなかんじをやりたいのです。
もちろん、これではエラーです
341:デフォルトの名無しさん
08/03/27 20:36:48
>>339
できないよ。
342:デフォルトの名無しさん
08/03/27 20:51:07
解答を待っているのかもしれないが、本当にできないから。
URLリンク(www.geocities.jp)
343:デフォルトの名無しさん
08/03/27 20:57:51
どうしてもそれっぽいことがやりたいなら
vector<Test>にひとつひとつpush_back()するか
ポインタの配列にしてひとつひとつnewすればいいんでないの
344:デフォルトの名無しさん
08/03/27 21:55:56
VC++6で
for(int i=0; i<10; i++){
...
}
for(int i=0; i<10; i++){
...
}
って書いたら
iの再定義っておこられた
拡張子cppになってるのに
345:デフォルトの名無しさん
08/03/27 21:57:25
仕様です
346:デフォルトの名無しさん
08/03/27 21:58:46
1998年発売のソフトやもん。
347:デフォルトの名無しさん
08/03/27 21:59:23
>>344
びっくりするくらいみんな知ってる。
規格準拠していないんだから何も問題ない。
348:デフォルトの名無しさん
08/03/27 22:01:35
>>344
#define for if(0); else for
魔法のおまじない
349:デフォルトの名無しさん
08/03/27 22:01:59
当時は準拠してたんだよ
350:デフォルトの名無しさん
08/03/27 22:03:21
まだ規格もなかったのに何に準拠してたというのか。
351:デフォルトの名無しさん
08/03/27 22:04:00
常識。
352:デフォルトの名無しさん
08/03/27 22:29:04
>324,329
だいたい、「関数ポインタ型」それ自体にはリンケージなんか無いだろ。
それともこーゆーコードが通るコンパイラでもあるのかっつーの。
typedef static void (*hoge)();
typedef extern void (*foo)();
typedef extern "C" void (*var)();
353:デフォルトの名無しさん
08/03/27 22:36:23
typedef void (*__stdcall type)();
こういうのならたまにやる。
354:デフォルトの名無しさん
08/03/27 22:36:46
それはリンケージじゃなくて呼び出し規約
355:デフォルトの名無しさん
08/03/27 22:48:31
>>350
ARM、ISOのドラフト
356:デフォルトの名無しさん
08/03/27 22:49:53
>>355
>>344 なていたらくでか
357:デフォルトの名無しさん
08/03/27 22:58:27
>>356
forの中で定義した変数の有効範囲が
直後のループ本体に限られるようになったのは
結構遅かったのでは?D&Eでも軽く触れられていたし。
それに加え過去の互換性のためVC6はあれがデフォルトになったんだと思う。
358:デフォルトの名無しさん
08/03/27 23:27:37
昔の人が考えた仕様には、頭おかしいだろうってのがそれなりに有るからね。
359:デフォルトの名無しさん
08/03/27 23:47:27
初期のコンパイラの実装の都合もあったんじゃないかな?
最近のコンパイラで、forの変数の有効範囲が限られるようになってるのに最近気づいて思わずGJと叫んだ。
360:デフォルトの名無しさん
08/03/28 00:10:34
>>357
まあ 1998 年と言えば規格が出る年だしな。
開発期間とか考えると多少前の仕様に準じようとしてたと考えるのが妥当だけど、
その時期ならドラフトとはいえかなりな部分まで練られてると思うんだけどな。
まあ、想像でしかないので本当にギリギリになって入れられた仕様なのかもしんないけど。
VC6 はテンプレートまわりがバグ持ちすぎてかなり酷いが、
テンプレートも遅くに入った仕様だからな・・・。
new がデフォで bad_alloc 投げないとか、とにかく色々と酷い上に、
しばらく次のコンパイラが出なかったという・・・。
361:デフォルトの名無しさん
08/03/28 00:18:58
未だに古いライブラリとかで使わないといけないことが結構あるからねぇ
VS2005から入った俺としては結構苦痛
まあでもテンプレートさえなければインテリセンス反映が早いのはよい
362:デフォルトの名無しさん
08/03/28 00:36:24
VC++6.0は当時の状況を考えればしょうがないと思う
問題なのは次のコンパイラがさっさと出なかった事
お陰で変に普及しちまって、このスレでもVC++6.0でコンパイルできません的な質問が絶えない
363:デフォルトの名無しさん
08/03/28 00:38:12
全てはMSが次期製品を確実に買ってくれる為に図った陰謀。
364:デフォルトの名無しさん
08/03/28 00:53:13
MSの事情的にはむしろ逆のような?
過去のシステムヘッダに, for で宣言した変数が
その後も生きることに依存したコードがあったっていう……
365:デフォルトの名無しさん
08/03/28 00:56:00
#define for if(0) else for
のおまじないと使ったあとでATLをincludeすると
怒られるちゅーか
366:デフォルトの名無しさん
08/03/28 01:14:53
>>363
そして満を持して登場した 2002 が糞だったという罠。
そして 2003 で大きく改善されるという二重の罠。
アカデミックだと無料アップグレードできないという三重の罠。
367:デフォルトの名無しさん
08/03/28 01:16:50
#define for if(0); else for は色々やった後にやるとよろし。
368:デフォルトの名無しさん
08/03/28 01:55:57
ってかincludeする前にundefするだろ・・・
369:デフォルトの名無しさん
08/03/28 02:11:01
>>336,352
ややこしくて嫌になるが、内部とか外部とかがある「リンケージ」と
"C" とか "C++" とかがある「言語リンケージ」("language linkage") とは
別物。 >324,329 が言ってるのは言語リンケージのほうなんで、話がまるで
かみ合ってない。
370:デフォルトの名無しさん
08/03/28 03:12:43
自信満々な>>336が可哀想に見えてきちゃったよw
逆にextern "C++"と同じという根拠は?ってのが哀愁をソソル
371:デフォルトの名無しさん
08/03/28 03:26:11
>>336
素の「リンケージ」の話だとしてもおかしい。静的メンバ関数のリンケージは
ほとんど外部リンケージになる。例外は関数内のクラスのメンバの場合とかね。
372:デフォルトの名無しさん
08/03/28 03:29:08
静的メンバ関数が「外部に公開されない」ってのもおかしいな。
クラスの宣言されたスコープや、クラス内での private なり public なりに
従うだろ、常考。
373:デフォルトの名無しさん
08/03/28 03:50:38
びやーんはもうC++なんか使っていないらしい。
374:デフォルトの名無しさん
08/03/28 05:40:45
ソースは?
375:デフォルトの名無しさん
08/03/28 07:19:26
2ch
376:デフォルトの名無しさん
08/03/28 08:03:31
>>372
public, privateと内部リンケージ, 外部リンケージはまた別の話だ
377:デフォルトの名無しさん
08/03/28 08:07:53
もう何がなんだかわからないよママン
378:デフォルトの名無しさん
08/03/28 09:26:26
>>359
もともとがCへのトランスレータだった事を考えれば自然に合点が行くね。
for( int i = 0 ; .... ) { ... }
変換後
{
int i ;
for( i = 0 ; .... ) { ... }
}
379:デフォルトの名無しさん
08/03/28 09:47:14
>>377
C++の仕様書を見ればいいと思うお
380:デフォルトの名無しさん
08/03/28 09:57:02
>>372
リンカなどの外部に公開され得るのはクラスであって内部リンケージであるメンバが同様に公開されているように見えるのは処理系の都合
381:デフォルトの名無しさん
08/03/28 11:33:58
>>380
クラスが外部リンケージを持つときに、メンバ関数が外部リンケージを持つかどうか は処理系依存だと言っているのならそれは違うよ
382:デフォルトの名無しさん
08/03/29 03:01:24
>>377 >329,324
383:デフォルトの名無しさん
08/03/30 01:04:01
テンプレートをつかうと一気にコンパイル時間が10倍に?!
384:デフォルトの名無しさん
08/03/30 01:07:31
>>383
>>5
385:デフォルトの名無しさん
08/03/30 15:11:26
template使っても
型が1個と100個じゃ大違いだろ
386:デフォルトの名無しさん
08/03/30 15:17:08
このテンプレいつの間にか一つのレスにまとめられてたのかw
387:デフォルトの名無しさん
08/03/30 15:27:00
template <typename Questioner>
int IsCompileTimeBecomeLongerByUsingTemplate() {
return ENVIRONMENT_DEPENDENT;
}
388:デフォルトの名無しさん
08/03/30 16:25:46
テンプレート無意味過ぎる
389:デフォルトの名無しさん
08/03/30 16:28:21
>>388
質問者に応じて別の回答をするように特殊化するんだよ。
390:デフォルトの名無しさん
08/03/30 16:36:16
template<> int IsCompileTimeBecomeLongerByUsingTemplate<教えて君>()
{
throw spoon();
}
391:デフォルトの名無しさん
08/03/30 16:59:30
匙は投げられた。
392:デフォルトの名無しさん
08/03/30 17:30:09
the biggest news of the meeting was that we voted lambda functions and closures into C++0x.
// Writing a collection to cout, in C++0x:
for_each( w.begin(), w.end(),
[]( const Widget& w ) { cout << w << " "; } );
393:デフォルトの名無しさん
08/03/30 17:59:38
スレ違い
394:デフォルトの名無しさん
08/03/31 01:28:23
LRESULT CALLBACKの関数をCLASSに所属させるにはどうすればできますか?
395:デフォルトの名無しさん
08/03/31 01:37:29
static
396:デフォルトの名無しさん
08/03/31 02:07:44
>>394
URLリンク(web.archive.org)
397:デフォルトの名無しさん
08/03/31 05:36:51
RTTIについて質問です。
RTTIありでオブジェクトファイルを生成したいが
外部libなどがRTTIを含んでいない場合は
自分側もそれにあわせてRTTIなしで組まなければ成らないのでしょうか?
398:デフォルトの名無しさん
08/03/31 10:26:48
コンパイラオプションでRTTIを使うかどうかの設定の話なら、ケースバイケース。
自分が知るVC++では、外部のオブジェクトに対してtypeidやdynamic_castをしなければ、
自プログラムがRTTI有効でも、問題なくリンクして実行できる。
逆にそうでない処理系も世の中あるかもしれない。
399:デフォルトの名無しさん
08/03/31 12:28:13
>>397
リンクでエラーが出たらオプション変えればいいんじゃないか?
400:デフォルトの名無しさん
08/03/31 17:21:40 BE:1614463687-2BP(200)
URLリンク(www.borland.co.jp)
が切れていてBorland C++ Compilerがダウンロードできないんだけど
401:デフォルトの名無しさん
08/03/31 17:25:43
>>400
普通にアクセスできるしスレ違いですさようなら
402:デフォルトの名無しさん
08/04/01 02:25:47
test
403:397
08/04/01 02:34:57
>>398
環境依存てことですかね~。
>>399
vcとのクロス開発あたりだとエラーがでてしまうのです;;
根本的になにをやりたいかというと、
シリアライズ機能を自前で実装しようと考えていまして
実装の際にRTTIのtypeidを利用して組むとらくそうなのですが・・・
ない場合はMFCやwxWidgetのようなクラス毎にマクロを仕組んで
独自の機構を作るしかないのかなって悩んでしまって・・
※boostのシリアライズという選択肢もありますが、boostが対応していない環境も考慮しました。