- ベストアンサー
static constメンバ変数(配列)の初期化について
C++初心者です。 constメンバ変数の初期化について教えてください。 クラスの中に、static constメンバ変数(配列)を持ちたいのですが、 <コード1> class hoge { public : hoge(){}; virtual ~hoge(){}; static const int fuga[2] = {1, 2}; }; とすると、VC++ 2005では、 error C2059: 構文エラー : '{' error C2334: '{' の前に予期しないトークンがありました。関数の本体は無視されます というエラーが発生します。 何がいけないのでしょうか? また、下の様にするとOKでした。 <コード2> class hoge { public : hoge(){}; virtual ~hoge(){}; static const int fuga[2]; }; const int hoge::fuga[2] = {1,2}; こうすればコンパイルが通る事は分かったのですが、なぜこんな面倒な事をしないといけないのかが分かりません。 コード1では何がいけないのでしょうか? 以上、よろしくお願いします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
> なぜこんな面倒な事をしないといけないのかが分かりません。 配列の実体の定義をひとつにするためです。 C++言語はC言語のスーパーセットですから、C言語とほぼ同様の特性を持っています。 この問題はC言語の知識があれば直感的に理解できるでしょう。 類似コードをC言語で書くと以下のようになります。 (もう、C言語は自信ないですが・・・) [hoge.h] typedef struct tagHoge { /* メンバ */ } Hoge; extern const int hoge_fuga[]; void hoge_initialize(Hoge*); void hoge_finalize(Hoge*); [EOF] [hoge.c] const int hoge_fuga[] = {1, 2}; void hoge_initialize(Hoge*) {} void hoge_finalize(Hoge*) {} [EOF] このコードは、extern で hoge_fuga という配列を外部参照し、 hoge.c ファイル中でその実態を定義するという単純なコードです。 hoge.c 以外のソースファイルで hoge_fuga の実体を定義すると多重定義でリンクエラーが起きてしまいます。 ですので、hoge.h をインクルードすることで外部参照宣言のみを行います。 もし質問者さんの最初のコードでコンパイルが通るとした場合、 hoge::fuga の実体は複数のソースファイルで定義されてしまう可能性が出てしまいますので、 その場合はC言語と同様にリンクエラーとなってしまうでしょう。 それならば、コンパイルも通さないほうが親切です。 ということで、最初のコードは通らないように規格が制定されたのでしょう。 なぜ、リンクエラーを起こすようになっているのかは、処理が複雑になり過ぎるためです。 コンパイル・リンク時間の増大やコンパイラ・リンカの不具合など、デメリットが大きすぎるんですね。 ちなみに、整数定数などは宣言と定義を同時にできますが、 これはサイズが小さく実体を複数作っても問題がないため、インライン展開や多重定義自体を許可することで実現しています。
その他の回答 (2)
- koedame
- ベストアンサー率33% (10/30)
まあ、私もよくはわからないけど、 通常のメンバ変数もクラスの定義内では初期化できないから。 恐らく同じ原理なのではないですか。 ・・・多分。
お礼
ありがとうございます。 でも、static型なので、 >通常のメンバ変数もクラスの定義内では初期化できないから。 >恐らく同じ原理なのではないですか。 という訳ではなさそうです。
- MrBan
- ベストアンサー率53% (331/615)
# 動作は仕様通り、(少なくとも現行仕様の範囲では)そういうものです>C++ > コード1では何がいけないのでしょうか? 言語仕様にそれを許可する記述がないから。 > こうすればコンパイルが通る事は分かったのですが、 > なぜこんな面倒な事をしないといけないのかが分かりません。 そういう言語仕様だから、ですかね。 ISO/IEC14882:2003 9.4.2 Static data membersあたりをご覧ください。 元々、整数定数などが宣言と定義を一緒にできるのは、 利便性のために、明示的にそれを許可する規定が盛り込まれたためです。 配列はここに規定されてません(許可されてるものの方が少ないです)。 # そもそも言語仕様Fix前のVC6みたいな古いコンパイラは、整数でも通らない…。
お礼
なるほど。仕様ですか。 ありがとうございます。
お礼
なるほど。 ありがとうございます。 頂いた回答を見ていて、また疑問に思う事がありましたので、ちょっと試してみて、それから改めて質問したいと思います。 ありがとうございました。