2012-09-19 21 views
7

:Foo.cppで静的定数クラスのメンバ宣言

class Foo 
{ 
public: 
    Foo(); 
    static const unsigned int FOOBAR = 10; 
    static const unsigned int BARFOO = 20; 

private: 
    unsigned int m_FooBar; 
    bool m_Bar; 
    void Bar(); 
}; 

Foo::Foo() 
    : m_FooBar(FOOBAR), // this works 
     m_Bar(false) 
{ 
} 

void Foo::Bar() 
{ 
    //m_FooBar = m_Bar ? FOOBAR : BARFOO; // linker fails *1 
    m_FooBar = FOOBAR; // ok 
} 

私はGCC 4.5.3でコンパイルしています。 line * 1のコメントを外したときにリンカーが失敗する理由はありますか?

Foo.o: In function 'Foo::Bar' (name unmangled): 
Foo.cpp: undefined reference to `Foo::FOOBAR' 
Foo.cpp: undefined reference to `Foo::BARFOO' 

VC2005、2008、2010およびCB2010で試してみました。彼らはすべてコンパイルされ、うまくリンクされています。 GCCはなぜこのケースで失敗するのですか?

answer hereが与えられているので、他の一般的なコンパイラがGCCのように失敗するのはなぜですか? GCCや他の一般的なコンパイラのバグでなければならない。それとももっと合理的な説明がありますか?クラス宣言の外

static const unsigned int FOOBAR = 10; 
static const unsigned int BARFOO = 20; 

+3

Hmm ... VS2010でうまくコンパイルされます。 – Mysticial

+0

CB2010とVS2005のコンパイルとリンク –

+1

@神秘的な質問はgccについてです。私はリンカのエラーを確認することができます。 –

答えて

4

正式には、ヘッダーは静的定数のみを宣言するだけでなく、(少なくともC++ 03では)定義する必要があります。ただし、その値のみを使用する場合は、ほとんどの場合、これを取り除きます。

C++ 11では、これは静的が "odr-used"のときに定義が必要であると、より正式に指定されています。 *1行がこれの例です。 3者演算子は値への参照を作成しようとし、コンパイラ(またはリンカは実際には)それができないことを認識します。


C++ 11標準は言うメンバーがまだそれならば、名前空間スコープで を定義するもの

9.4.2静的データメンバ
§3...プログラムでodr-used(3.2)であり、ネームスペーススコープ定義は、イニシャライザを含んでいてはならない( )。

+0

しかし、C++ 03の整数静的定数は、質問のようにヘッダで宣言され定義されていれば問題ありません。 –

+0

値を使うだけで問題ありません。トライアド演算子は、2つの値のいずれかへの参照を生成します。これは、定義されていない場合は不可能です。関数の参照によって値の1つを渡そうとすると、同様の効果が得られます。 –

+0

他の普及しているコンパイラはなぜそうしていないのですか?トライアディックオペレータがそれを行うならば、VC2010でも失敗しないでしょうか? –

0

は、これらのメンバーを定義してみます。

Foo::FOOBAR = 10; 
Foo::BARFOO = 20; 
関連する問題