ページ 11

class定数を定義したいですが

Posted: 2009年5月19日(火) 10:29
by ABC
いつもお世話になっております

例えば、
class ABC
{
static const x = 100; // OK

static const y[/url] = {100,200,300}; // コンパイラエラー:{ が関数外に存在する。 云々


}

今回ちょうど配列(y[/url])のような定数シリーズを定義したいんで、どうすればいいのでしょうか


どうぞ宜しくお願いします。

Re:class定数を定義したいですが

Posted: 2009年5月19日(火) 10:31
by Blue
ヘッダは宣言のみにしてcppに定義を書いてみてはどうでしょうか?

ちなみに型名はちゃんと宣言しましょう。

Re:class定数を定義したいですが

Posted: 2009年5月19日(火) 13:51
by ABC
ご返答ありがとうございます。

書き直しますと下記のようになりますが

class ABC
{
private:

static const int x = 100; // OK

static const int y[/url] = {100,200,300}; // コンパイラエラー:{ が関数外に存在する。 云々


}

現象は変わりません。

なぜ xはOK, y[/url]はだめでしょうか。
実現方法ありますか

宜しくお願いいたします

Re:class定数を定義したいですが

Posted: 2009年5月19日(火) 14:33
by 御津凪
Blue さんの通り、クラスの static メンバ変数はクラス定義の外(.cpp ファイル内)で初期化を行うのが普通です。
クラス内で初期化を行っている時、そのクラスが複数のソースからインクルードされている場合はリンカエラーが出ます。
(重複したシンボル名とか云々)

また、

> static const int y[/url] = {100,200,300}; // コンパイラエラー:{ が関数外に存在する。 云々

これがコンパイルエラーなのは、単にクラス内で配列を初期化できないから(仕様?)です。

クラス内の static メンバ変数の正しい初期化の仕方は以下のようになります。
// ヘッダファイル内
class ABC 
{ 
private: 
    static const int x;
    static const int y[/url];
    // ↑宣言のみ
};

// cpp ソースファイル内(上記のヘッダをインクルードすること)
const int ABC::x = 100;
const int ABC::y[/url] = {100,200,300};
// ↑ static は不要
ちなみに、配列を使わないクラス定数(かつ整数)なら enum を使用することで
初期化部分を別にする必要はなくなります。

Re:class定数を定義したいですが

Posted: 2009年5月19日(火) 14:41
by たかぎ
> ちなみに、配列を使わないクラス定数(かつ整数)なら enum を使用することで
> 初期化部分を別にする必要はなくなります。

いわゆるenumハックという手法ですが、それは標準準拠度の処理系への対策です。
まともなコンパイラであれば、const修飾子が付いた汎整数型の静的メンバ変数は、クラス定義の際に初期化子を指定することができます。

Re:class定数を定義したいですが

Posted: 2009年5月19日(火) 15:34
by ABC
御津凪 さま、たかぎ さま

ご教授ありがとうございます。

やりかたはよく分かりました。

いま MS VC++ 2008 を使っています。

御津凪 さまが書かれました:
> そのクラスが複数のソースからインクルードされている場合はリンカエラーが出ます。
意味はよく分かりました。正しいと思います。

ただ、これだと、classというスコープの意義がなくなったような感じですね。

現にメンバー関数もクラスの中に定義していて、クラスが複数のソースからインクルードされていますが
関数の再定義エラーは出ませんでした。

なぜか、MS VC++ はメンバー関数と静的なメンバー変数に違う論理で取り扱われているようですね。


たかぎ さまが書かれました:
> const修飾子が付いた汎整数型の静的メンバ変数は、クラス定義の際に初期化子を指定することができます。

JAVA言語はこうなっています。
こうならないのはC++の仕様のせいか、それとも特定のC++のコンパイラーのせいでしょうか。