![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
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では何がいけないのでしょうか?
以上、よろしくお願いします。
No.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言語と同様にリンクエラーとなってしまうでしょう。
それならば、コンパイルも通さないほうが親切です。
ということで、最初のコードは通らないように規格が制定されたのでしょう。
なぜ、リンクエラーを起こすようになっているのかは、処理が複雑になり過ぎるためです。
コンパイル・リンク時間の増大やコンパイラ・リンカの不具合など、デメリットが大きすぎるんですね。
ちなみに、整数定数などは宣言と定義を同時にできますが、
これはサイズが小さく実体を複数作っても問題がないため、インライン展開や多重定義自体を許可することで実現しています。
なるほど。
ありがとうございます。
頂いた回答を見ていて、また疑問に思う事がありましたので、ちょっと試してみて、それから改めて質問したいと思います。
ありがとうございました。
No.2
- 回答日時:
まあ、私もよくはわからないけど、
通常のメンバ変数もクラスの定義内では初期化できないから。
恐らく同じ原理なのではないですか。
・・・多分。
ありがとうございます。
でも、static型なので、
>通常のメンバ変数もクラスの定義内では初期化できないから。
>恐らく同じ原理なのではないですか。
という訳ではなさそうです。
No.1
- 回答日時:
# 動作は仕様通り、(少なくとも現行仕様の範囲では)そういうものです>C++
> コード1では何がいけないのでしょうか?
言語仕様にそれを許可する記述がないから。
> こうすればコンパイルが通る事は分かったのですが、
> なぜこんな面倒な事をしないといけないのかが分かりません。
そういう言語仕様だから、ですかね。
ISO/IEC14882:2003 9.4.2 Static data membersあたりをご覧ください。
元々、整数定数などが宣言と定義を一緒にできるのは、
利便性のために、明示的にそれを許可する規定が盛り込まれたためです。
配列はここに規定されてません(許可されてるものの方が少ないです)。
# そもそも言語仕様Fix前のVC6みたいな古いコンパイラは、整数でも通らない…。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Boolean型配列中のTrueの有無を...
-
「オブジェクトが必要です。」...
-
Excel VBA の ChangeFileAccess
-
ボタンをクリックすると数が増...
-
Javascriptグローバル変数の値...
-
MFCのキャプション変更
-
【Jquery】changeイベント毎にa...
-
Linux バイナリ実行できない "...
-
2次元のJSON形式の配列の展開
-
同じ型【ハイフンと数字】だけ...
-
responseTextを使っての書き換...
-
-(ハイフン)_(アンダーバー)の...
-
関数でy=g(x)のgとは何の略です...
-
window.openでタイトル名の指定
-
innerHTML実行後のイベント
-
食材の期限を管理するためにGAS...
-
同じIDで定義した要素の配列を...
-
idを使わずにonclickで自身の要...
-
C#OpenCv V4にのエラーに関する...
-
div要素内の全input要素をdisable
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Boolean型配列中のTrueの有無を...
-
【正規表現】【javascript】CR...
-
Linux バイナリ実行できない "...
-
ボタンをクリックすると数が増...
-
HTTPSのとき":"が"%3A"ではなく...
-
Excel VBA の ChangeFileAccess
-
Vb.netのグローバル変数の宣言...
-
ASP+アクセスでのSQLコメントに...
-
【Jquery】changeイベント毎にa...
-
「オブジェクトが必要です。」...
-
C# .NET DataGridView の行を追...
-
static constメンバ変数(配列)...
-
MFCのキャプション変更
-
hoge の謎
-
javascriptで文字挿入でtoggle...
-
onclick指定関数の引数へローカ...
-
複数ファイルで使うグローバル...
-
バイナリファイルから文字列を...
-
ifreamをリロードしたい
-
正規表現で半角数字1桁のみを全...
おすすめ情報