1 名前:v(^・^)v [2007/09/26(水) 03:41:13 ] C++に関する質問やら話題やらはこちらへどうぞ。 ただし質問の前にはFAQに一通り目を通してください。 IDE (VC++など)などの使い方の質問はその開発環境のスレに お願いします。 テンプレその他 >>2-15 付近参照 前スレ(実質 part57) C++相談室 part56 pc11.2ch.net/test/read.cgi/tech/1185377587/
89 名前:デフォルトの名無しさん mailto:sage [2007/09/30(日) 08:57:57 ] あ、ごめん。勘違い。 スルーして下さい。
90 名前:デフォルトの名無しさん mailto:sage [2007/09/30(日) 18:33:43 ] VC2003で作られた 静的なlibは、 VC2005でリンクすることは不可能なんですか?
91 名前:デフォルトの名無しさん [2007/09/30(日) 20:19:13 ] クラスの内側で定義したクラステンプレートを特殊化する、 class X { template<typename T> class Y {}; template<> class Y<int> {}; }; のようなコードは、VC++(2003/2005)ではコンパイルできますが、g++3/4では error: explicit specialization in non-namespace scope ‘class X’ というエラー になってしまいます。 Y<int>をXの中ではなく、名前空間スコープで template<> class X::Y<int> {}; と書けばg++でもVC++でも問題なく特殊化できることは知っているのですが、 なんとかg++で、特殊化されたクラスの定義をXの中に書く方法はないでしょうか? Y<T>とY<int>の定義が離れた場所にあると、コードが読みにくいと思うのです。 boost(特にmpl)の使用は歓迎です。 よろしくおねがいします。
92 名前:デフォルトの名無しさん mailto:sage [2007/09/30(日) 20:27:59 ] >>89 クラス末尾にセミコロンがありませんでした。ごめんなさい。 とちゃんと書こうYO!
93 名前:デフォルトの名無しさん mailto:sage [2007/09/30(日) 20:42:48 ] >>91 定義位置を近づけたいなら、両方クラス外に書けばいいんじゃね?
94 名前:91 [2007/09/30(日) 20:45:33 ] >>93 ああ、たしかにそうですね。他に案がなければそうしたいとおもいます。 ただ、Y<T>とY<int>を両方クラス内に書けると、宣言と定義の位置も離れない(定義だけになる)ので、 より読みやすいと思っています。 というわけで、引き続きお願いします。
95 名前:デフォルトの名無しさん mailto:sage [2007/09/30(日) 20:54:22 ] >>91 規格ではネストされたクラス内での明示的特殊化は禁止されているけど 部分特殊化はOKなので、 class X { template <typename T, class U = void> class Y {}; template <typename T> class Y< T , typename boost::enable_if< typename boost::is_same< T, int> > > {}; }; のようにenable_ifとis_sameを使って書くといいっぽい(初心者スレから一部拝借w) VCでコンパイル可能なのはmsの独自拡張でgccの方が正しいとのこと
96 名前:91 [2007/09/30(日) 20:57:38 ] なお、メンバ関数テンプレートで同様のエラーをくらう件については (下記の2行めがエラーになる)、 class X { template<typename T> void foo(T x) {} template<> void foo<int>(int x) {} // error }; 下記方法でごまかしています。 #include <boost/type.hpp> class X { void foo_(int x, boost::type<int>) { /* specialized */ } template<typename T> void foo_(T x, ...) {} public: template<typename T> void foo(T x) { foo_(x, boost::type<T>()) ;} };
97 名前:91 mailto:sage [2007/09/30(日) 20:59:12 ] >>95 部分特殊化はOKだったんですか。気づきませんでした。 早速試してみます。どうもありがとう〜!!
98 名前:デフォルトの名無しさん mailto:sage [2007/09/30(日) 21:00:46 ] >>91 私はC++初心者ですが、>>93 さんと同意見です。 >>95 さんの言うようにgccの方が正しい(つまり規格どおりということですよね)ならば、 なおさらそう思います。 それに、Xクラスの定義を見たいときには、むしろYは外にあった方が見やすいのではないでしょうか?
99 名前:デフォルトの名無しさん mailto:sage [2007/09/30(日) 21:06:58 ] ちなみに関数テンプレでもこの手は使えるようだ この手法も名前があったと思うけど思い出せない 使うなら適当にローカルなメタ関数を専用の名前空間に自作して階層を浅くする工夫が必要だね 使ってればわかるけど、凄く見にくくなるから
100 名前:デフォルトの名無しさん mailto:sage [2007/09/30(日) 21:10:12 ] あ、::type付けわすれた…
101 名前:デフォルトの名無しさん mailto:sage [2007/09/30(日) 21:43:54 ] 読み易くするのが目的で読みにくくなる手法を選ぶか。 >>99 名前があるならソレをコメントに書いておけば良いかも。
102 名前:デフォルトの名無しさん mailto:sage [2007/09/30(日) 22:00:44 ] >>98 >>101 読みやすいかどうかは読み手にもよるし、あまり>>91 や>>94 はよい聞きかたではなかったですね。 C++のコードを自動生成するツール(自作)の都合でX内に定義を書けると嬉しい、というのが実際の事情です。
103 名前:91 mailto:sage [2007/09/30(日) 22:32:03 ] 102は91です。 >>99 concept-controlled polymorphism ですか?
104 名前:デフォルトの名無しさん [2007/09/30(日) 23:06:47 ] >>100 > あ、::type付けわすれた… 検索エンジン経由で来るひとのために、一応訂正版貼っときますね。 #include <cstdio> #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_same.hpp> struct X { template<typename T, typename U = void> struct Y { Y() { std::printf("genecic\n"); } }; template<typename T> struct Y <T, typename boost::enable_if<boost::is_same<T, int> >::type> { Y() { std::printf("specialized for int\n"); } }; }; class Z {}; int main() { X::Y<Z> a; X::Y<int> b; X::Y<float> c; } 実行結果は、 genecic specialized for int genecic です。
105 名前:91=104 mailto:sage [2007/09/30(日) 23:31:30 ] boostが使えない場合は、VC++2003/2005/g++対応だけ考えるならこんな感じでしょうか。 #include <cstdio> namespace b00st { template <bool B, class T = void> struct enable_if_c { typedef T type; }; template <class T> struct enable_if_c<false, T> { /* NO TYPEDEF! */ }; template <class Cond, class T = void> struct enable_if : public enable_if_c<Cond::value, T> {}; template<bool b> struct bool_ { static const bool value = b; }; template<typename T, typename U> struct is_same : bool_<false> {}; template<typename T> struct is_same<T, T> : bool_<true> {}; } using namespace b00st; struct X { template<typename T, typename U = void> struct Y { Y() { std::printf("genecic\n"); } }; template<typename T> struct Y<T, typename enable_if<is_same<T, int> >::type> { Y() { std::printf("specialized for int\n"); } }; }; そろそろウザいとおもうので、これで打ち止めにします。ありがとうございました。
106 名前:デフォルトの名無しさん mailto:sage [2007/09/30(日) 23:40:10 ] このtemplate感、実に小気味良い 久しぶりにC++スレを実感した
107 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 00:01:02 ] キモ
108 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 00:04:13 ] 小気味良いのは確かだけど、言葉遣いが丁寧すぎてちょっと痒い、というのが俺の感想。 うん、俺の感想なんかどーだっていいってのは承知。
109 名前:デフォルトの名無しさん [2007/10/01(月) 02:02:08 ] >>99 enable_ifの関数テンプレへの適用で質問。ある条件で2つの関数を呼びわけたいときは、こんな感じにすればいいみたいだけど、 template<typename T> static void foo(T t, typename boost::disable_if<boost::is_same<T,int> >::type* = 0) { } template<typename T> static void foo(T t, typename boost::enable_if<boost::is_same<T,int> >::type* = 0) { // intへの特殊化版 } 3つ以上を呼びわけるにはどうすれば? たとえば、 template<int V> static void boo(typename boost::enable_if_c<V == 0>::type* = 0) { } template<int V> static void boo(typename boost::enable_if_c<V == 1>::type* = 0) { } template<int V> static void boo(typename boost::disable_if_c<V == 0 || V == 1>::type* = 0) { // default } とかだと、default caseな関数の引数が大変なことになってしまうような。 boostスレのほうがいいのかな。。
110 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 02:51:44 ] 複雑な場合はmplの出番になるんじゃないかな mpl::if_< ..., mpl::if_< ..., > >::type::call();
111 名前:109 [2007/10/01(月) 03:23:49 ] >>110 すみません、それはどこに書くコードなんでしょうか? call() とは一体。。
112 名前:109 [2007/10/01(月) 03:28:24 ] >>110 が理解できず、独自に考察を進め中。 template<int V> static void boo(typename boost::enable_if_c<V == 0>::type* = 0) {} は、 template<int V> static void boo(typename boost::enable_if< boost::is_same< boost::mpl::int_<V>, boost::mpl::int_<0> > >::type* = 0) {} であり、さらに template<int V> static void boo(typename boost::enable_if< typename boost::mpl::lambda< boost::is_same< boost::mpl::_1, boost::mpl::int_<0> > >::type::apply<boost::mpl::int_<V> >::type >::type* = 0) {} だから、この数値0-Nでlambdaしたのをmpl::listで抱えて、特殊化版はlistのat<i>したのでenable_ifして、default版はこれらをandでfoldしたのにdisable_ifすればいいと思うんだぜ? ・・・絶対方向が間違ってる。
113 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 03:37:53 ] いや、単に、mpl::if_で関数を実装したクラスを選んで呼び出す boost/smart_cast.hppが参考になるかも
114 名前:デフォルトの名無しさん [2007/10/01(月) 03:44:43 ] >>113 私は、単に boo(0); boo(1); boo(2); とだけ書くと、呼び先の関数がコンパイル時に決まるようにしたいと 思っているんですが、>>110 は、このbooを *呼ぶ側* をif_で工夫しろということ? まぁ、boo()でif_を使って、適切なboo_()を呼ぶようにしてもいいのかもしれませんが、 委譲してしまうとタグディスパッチと大差ないようにも思うし。。 なんか勘違いしてたらすんません。smart_castは早速見てみます。
115 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 04:37:09 ] どうしてもenable_ifを使いたいなら 複雑な条件を書かずに済ますことは不可能だと思う
116 名前:109 [2007/10/01(月) 05:41:56 ] >>115 enable_ifが使いたいわけでは無くて、 1.メンバ関数テンプレートの特殊化(相当のこと - オーバーロードでもいい)を行いたい 2.特殊化の定義は、クラス内に書きたい (>>91 と同じく, 見た目の問題で) 3.メンバ関数を呼ぶ側はあまり難しいことを考えたくない 4.タグディスパッチのような別関数への処理の委譲は、できれば避けたい (これも見た目の問題で) という条件で、Pという場合と!Pという場合の処理の振り分けだったら、 enable_ifを使ったオーバーロードでOKとわかった(>>109 )が、P, Q, (!P && !Q) の3関数に振り分けたい場合にこの4条件を満たすようなのないですかね? というのが質問です。ちゃんと書かずにすみません。コンパイラはgccです。
117 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 05:47:44 ] >この4条件を満たすようなのないですかね 自分で書いた>>109 が満たしてると思うんだが
118 名前:デフォルトの名無しさん [2007/10/01(月) 05:58:35 ] >>117 おっしゃる通りなんですが、>>109 は、V==0やV==1という条件が 繰り返し登場してしまい、メンテナンス性がいまいちかなと思いまして。 実際はenumとか扱いたいので。 109の繰り返しになりますけど、条件1-4をみたし、かつdefault case template<int V> static void boo(typename boost::disable_if_c<V == 0 || V == 1>::type* = 0) { /* default */ } を綺麗にかけないですかね。 template<int V> static void boo(...) { /* default */ } とかが通れば最高なのに。
119 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 06:02:23 ] struct a_condition : mpl::bool_<...> {}; としてenable_ifに渡すとか
120 名前:デフォルトの名無しさん [2007/10/01(月) 09:08:09 ] kwsk
121 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 09:54:53 ] 引数忘れた こんな感じ enable_if< my_conditionA<V> > まあディスパッチすべきだな enable_ifはこの場合必要ないから
122 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 11:56:27 ] デザパタのプロトタイプパターンを使ってみたいのですが ばらばらに clone() 関数をとりつけるよりも ひとつ Clonable クラスを作って、そのクラスから 継承したほうがよいでしょうか?
123 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 12:34:46 ] そういう継承ってどうなんだろうね。
124 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 17:41:51 ] noncopyableとかあるし、いいんじゃね?
125 名前:デフォルトの名無しさん mailto:sage [2007/10/01(月) 18:16:10 ] traitsを作れば継承はいらないと思うよ
126 名前:デフォルトの名無しさん mailto:sage [2007/10/02(火) 21:42:40 ] #include <boost/numeric/ublas/vector.hpp> using namespace boost::numeric::ublas::inner_prod; VC++2005EEの環境でビルドすると、 error C2867: 'boost::numeric::ublas::inner_prod' : は名前空間ではありません。 というエラーが出ます。 エラーの原因は何ですか?
127 名前:デフォルトの名無しさん mailto:sage [2007/10/02(火) 22:08:58 ] 名前空間ではないものをusing namespaceしたこと
128 名前:126 mailto:sage [2007/10/02(火) 23:00:22 ] >>127 sealsoft.jp/namespace.html このサイトの > usingを使って、ある識別子をグローバルな名前空間に持ち上げることができる。こうするとその後は大域解決演算子を使う必要がない。 > using namespace seal::foo; > // 関数fooを呼び出す > int a = foo(); ここ見てできると思ったんですけど、このサイト間違ってますか?
129 名前:デフォルトの名無しさん mailto:sage [2007/10/02(火) 23:27:47 ] usingディレクティブ (using namespace)の対象にできるのは、名前空間だけ。 代わりといってはアレだが、その他の識別子一般には、using宣言が使える。 using boost::numeric::ublas::inner_prod;
130 名前:126 mailto:sage [2007/10/02(火) 23:49:25 ] >> 129 なるほど、そうなんですか。 msdn2.microsoft.com/ja-jp/library/6f133eff (vs.80).aspx ここを勘違いして見てました。(classの中のusingとは別物なんですね) クラスの中でnamespace内の関数をusingしたい場合、 class A { using boost::numeric::ublas::inner_prod; }; エラーになってしまうのですが、クラス中でnamespace内の関数をusingするのは無理ということですか?
131 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 00:09:31 ] そういうこと。クラス定義内のusingは基底クラスの名前を指定することに特化している。 なお、型名だけはtypedefで代用できる。
132 名前:126 mailto:sage [2007/10/03(水) 00:14:05 ] ありがとうございました。
133 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 01:54:49 ] マクロ使って、行数と引数を連結させたいのですが、 #define macro( name )\ const char *x = "name##__LINE__"; とかやってもできません。 こんなことは可能ですか?
134 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 02:05:02 ] __LINE__は定数だからダブルクォーテーションで囲っちゃだめっしょ で、定数を文字列にするのは単純なマクロじゃ厳しいと思うけど・・・ おとなしく関数にしたほうがよさそう
135 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 02:07:38 ] 一応マクロでこんな感じでいかが? #define macro( buf, name ) sprintf( buf, "%s%d", "name", __LINE__);
136 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 02:10:53 ] #define NUM2TEXT_(n) #n #define NUM2TEXT(n) NUM2TEXT_(n) #define macro(name) \ const char *x = name ## NUM2TEXT(__LINE__)
137 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 02:43:41 ] 演算子オーバーロードって副作用完了点のことも考慮しないといけないんですか? std::cout << "test" << std::endl; で (a) "test" << std::endl; が先に評価されて、次に std::cout << (a) が評価される、という事態にはならないんですか?
138 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 03:26:56 ] 優先順位の同じ演算子の並びは左から評価じゃなかったのか
139 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 04:07:20 ] 左結合と右結合があってね・・・
140 名前:133 mailto:sage [2007/10/03(水) 05:13:05 ] ありがとうございます。 >>136 さんのは どういう原理なんでしょうか?
141 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 08:46:05 ] 7**7**7 の下一桁の数字は?
142 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 09:44:47 ] >>137 多重定義されている場合、通常の関数と同様、 呼出の直前に副作用完了点が現れるので心配は要らない。 <<は左結合だから、まずstd::cout << "test"から取り掛かる。 これは多重定義されているので、std::cout.operator <<("test")という関数呼出に相当。 関数呼出の直前には副作用完了点が来るので、ここまでにstd::coutと"test"が評価される。 と言っても、共に副作用を持たないので何も起きないが。 仮に副作用を持つ式だった場合、通常の関数呼出同様に <<の左側と右側のどっちのオペランドが先に評価されるかは決まっていない。 std::cout.operator <<("test")の戻り値をrとすると、 次にr << std::endlの評価に掛かる。以下同じ。
143 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 11:51:51 ] >>140 > 16.3.2 The # operator > 16.3.3 The ## operator
144 名前:デフォルトの名無しさん mailto:sage [2007/10/03(水) 13:50:35 ] >>133 #define XY(X,Y) X##Y #define MAKENAMEXY(FX,LINE) XY(FX,LINE) #define MAKENAME(FX) MAKENAMEXY(FX,__LINE__) というマクロで連結させている例がある。 評価順その他の関係で、間に一段置かないとならないらしい。
145 名前:デフォルトの名無しさん mailto:sage [2007/10/04(木) 00:31:45 ] VS2008EEで>>136 が正常に動作しないんだけど・・・ コンパイラの仕様かな?
146 名前:デフォルトの名無しさん mailto:sage [2007/10/04(木) 00:36:58 ] プリプロセッサの仕様じゃね?とかつまんない事言うね。義務として。
147 名前:デフォルトの名無しさん mailto:sage [2007/10/04(木) 00:45:12 ] すみません。継承について質問です。 クラスBaseを基底とするクラスDerivAやクラスDerivBがあるとして、 そこからインスタンスを作成するとすると、 Base* pA = new DerivA; Base* pB = new DerivB; となると思います。 そこから、pAもしくはpBから新たなインスタンスpCを作りたいと思っているのですが、 どうしたらいいでしょうか? 単にpA(DerivA)だけであれば、DerivA *pC=*pAだけでいけるのですが、 pAとpB(最終的にはBaseを基底とするクラス全部)にも対応できるものを作りたいので、 どうか力をお貸しください。
148 名前:デフォルトの名無しさん mailto:sage [2007/10/04(木) 00:53:05 ] class Base { public: virtual Base *NewInstance() = 0; }; class DerivA : public Base { public: virtual Base *NewInstance(){ return new DerivA; } }; class DerivB : public Base { public: virtual Base *NewInstance(){ return new DerivB; } }; Base *pA = new DerivA; Base *pB = new DerivB; Base *pC = pA->NewInstance(); Base *pD = pB->NewInstance();
149 名前:デフォルトの名無しさん mailto:sage [2007/10/04(木) 00:53:41 ] Base* pA = new DerivA(); Base* pB = new DerivB();
150 名前:147 mailto:sage [2007/10/04(木) 01:02:02 ] >>148 、149 目からウロコが落ちました。 インスタンスを作成する関数を別途で作ればいいわけですね。 ありがとうございます。
151 名前:デフォルトの名無しさん mailto:sage [2007/10/04(木) 01:04:17 ] >>148 DerivA::NewInstanceはDerivA*を返し、 DerivB::NewInstanceはDerivB*を返し、 という具合に、そこは共変にしてほしいな。
152 名前:デフォルトの名無しさん [2007/10/04(木) 01:06:08 ] 凶変を許したことでできるようになったことってなんだっけ? なんかの本にかいてあったが忘れた
153 名前:デフォルトの名無しさん [2007/10/04(木) 01:15:57 ] >>136 boostにはなんて名前で入ってたっけ
154 名前:デフォルトの名無しさん mailto:sage [2007/10/04(木) 01:18:23 ] >>152 pAはDerivA*と分かっているとき、 DerivA* pA2 = static_cast<DerivA*>(pA->NewInstance()); のようなキャストを型安全性を損なうことなく排除できる。
155 名前:デフォルトの名無しさん [2007/10/04(木) 02:07:15 ] dynamic_castすれば共変なしでも安全じゃね?
156 名前:デフォルトの名無しさん mailto:age [2007/10/04(木) 02:08:25 ] videointroplayer.web.fc2.com/?ii9YN1kO-TK36%+WhqyiIrhz0F110%+Kjtps4byn7a119%+esA5NHPWRF1115%+026mGIi9Z4824%+@1@_KeyboardCrusher
157 名前:デフォルトの名無しさん mailto:sage [2007/10/04(木) 02:29:39 ] >153 BOOST_PP_STRINGIZE
158 名前:デフォルトの名無しさん mailto:sage [2007/10/04(木) 08:19:17 ] これじゃだめなん? Base *pC = new DerivC;
159 名前:デフォルトの名無しさん mailto:sage [2007/10/04(木) 08:20:10 ] Base *pC = new DerivC(pA); Base *pC = new DerivC(pB);
160 名前:デフォルトの名無しさん mailto:sage [2007/10/04(木) 21:28:42 ] >>155 それだと余計な負荷がかかる。
161 名前:デフォルトの名無しさん mailto:sage [2007/10/05(金) 01:29:04 ] 俺的c++開発環境構築メモ 目的:最終的にlinuxで動かせるようにしないといけないけどVisual Studio捨てれない winxpにvmwareいれてゲストOSとしてubuntu7を入れる ubuntuの/home/srcをsambaで共有できるようにしてホストOSのwinxpからみれるようにする /home/src = \\ubuntu\src の下にVisual Studioのプロジェクト作成 makefileはeclipse/CDTで自動生成 あとはemacsでメインのコードの編集するけど、flymakeとか使いつつ インテリセンスも使えてeclipse/cdtのリファクタリング機能も使える環境のできあがり
162 名前:デフォルトの名無しさん mailto:sage [2007/10/05(金) 04:20:16 ] 俺がいる
163 名前:デフォルトの名無しさん mailto:sage [2007/10/05(金) 08:18:16 ] もう遅いだろうがcoLinuxを薦めてみる
164 名前:デフォルトの名無しさん [2007/10/05(金) 12:27:41 ] coMomongaを勧めてみる
165 名前:デフォルトの名無しさん mailto:sage [2007/10/05(金) 12:59:49 ] coLinuxの方が便利なの? 速度が速い以外のメリットがないなら、もう乗り換えれない
166 名前:デフォルトの名無しさん mailto:sage [2007/10/05(金) 15:23:45 ] coLinuxってkernelのバージョンあがるたびに中身を全消ししないといけないって聞いたのだけど 違うの?
167 名前:デフォルトの名無しさん mailto:sage [2007/10/05(金) 17:36:55 ] ヘッダファイルなどで記述したグローバルなstatic変数は, includeしたソースが複数ある(各ソースではincludeガードが起きずに展開される) 場合も単一の存在となるんでしょうか? それとも別々の独立した変数となるんでしょうか?
168 名前:デフォルトの名無しさん mailto:sage [2007/10/05(金) 17:41:00 ] それをインクルードしたソースファイルごとに別々に作られることになる
169 名前:デフォルトの名無しさん mailto:sage [2007/10/05(金) 18:02:52 ] ありがとうございます. あれ,でもクラス変数などは単一なんですよね? うーむ,基本の理解が全然出来ていない.
170 名前:デフォルトの名無しさん mailto:sage [2007/10/05(金) 18:26:17 ] クラスの static 変数はどこかで1個だけ実体を定義する必要がある。 class A{ static int x; }; int A::x; // <-- これ 2個以上のソースファイルで定義したら、定義が重複してるってリンクエラーになる。 static でない普通のグローバル変数と同じあつかい。
171 名前:デフォルトの名無しさん mailto:sage [2007/10/05(金) 20:36:51 ] #includeは単にファイルをくっつけてるものと考えれば理解しやすいかも