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を探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・【お題】絵本のタイトル
- ・【大喜利】世界最古のコンビニについて知ってる事を教えてください【投稿~10/10(木)】
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・ハマっている「お菓子」を教えて!
- ・最近、いつ泣きましたか?
- ・夏が終わったと感じる瞬間って、どんな時?
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Vb.netのグローバル変数の宣言...
-
複数ファイルで使うグローバル...
-
2次元のJSON形式の配列の展開
-
HTTPSのとき":"が"%3A"ではなく...
-
Excel VBA の ChangeFileAccess
-
Linux バイナリ実行できない "...
-
Boolean型配列中のTrueの有無を...
-
エクセルでブラウザへのフォー...
-
関数を呼び出すHTMLタグ<body o...
-
【正規表現】【javascript】CR...
-
GASでundefinedエラーが出ます
-
今日からnヶ月後(前)
-
jQuery|要素だけを変更できま...
-
idを使わずにonclickで自身の要...
-
<a>タグのテキストを取得
-
jspからjavascriptの変数引継ぎ
-
javascriptでiframeのURL変更は?
-
ジェネレーターの作り方
-
functionから別のfunctionを実...
-
関数でy=g(x)のgとは何の略です...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Boolean型配列中のTrueの有無を...
-
ASP+アクセスでのSQLコメントに...
-
Linux バイナリ実行できない "...
-
【正規表現】【javascript】CR...
-
Vb.netのグローバル変数の宣言...
-
Excel VBA の ChangeFileAccess
-
javascriptで文字挿入でtoggle...
-
HTTPSのとき":"が"%3A"ではなく...
-
「オブジェクトが必要です。」...
-
複数ファイルで使うグローバル...
-
C# .NET DataGridView の行を追...
-
【Jquery】changeイベント毎にa...
-
ボタンをクリックすると数が増...
-
URLの一部をコピーできるブック...
-
static と externについて
-
バイナリファイルから文字列を...
-
ifreamをリロードしたい
-
class指定したHTML要素の背景色...
-
VC++のちらつき防止方法
-
サブウインドウから親ウインド...
おすすめ情報