2012-09-19 24 views
7

in foo.h:statica costante dichiarazione di membro della classe

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(); 
}; 

in Foo.cpp:

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 
} 

Sto compilando con GCC 4.5.3. C'è qualche ragione per cui il linker fallirebbe quando la riga * 1 non è commentata?

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

provato con VC2005, 2008, 2010 e CB2010. Hanno tutti compilato e collegato bene. Perché GCC fallisce in questo caso?

Dato il answer here, perché gli altri compilatori popolari non funzionano come GCC? In un modo o nell'altro, deve essere un bug, sia per GCC che per gli altri popolari compilatori. O c'è una spiegazione più ragionevole?

+3

Hmm ... Compone bene in VS2010. – Mysticial

+0

Compilate e collegamenti anche in CB2010 e VS2005 –

+1

@Misticial domanda riguarda comunque gcc. e posso confermare l'errore del linker. –

risposta

4

Formalmente, l'intestazione dichiara solo le costanti statiche, e devono anche essere definito (almeno in C++ 03). Tuttavia, se usi solo i loro valori, molto spesso te ne vai via.

In C++ 11 questo è più formalmente specificato come richiedere una definizione quando la statica è "odr-used". La linea *1 è un esempio di questo. L'operatore triadico cerca di formare un riferimento ai valori, e il compilatore (o il linker in effetti) si rende conto che non può.


Lo standard C++ 11 dice

9.4.2 membri dati statici
§3 ...
Il membro deve ancora essere definito in un ambito spazio dei nomi se è odr-used (3.2) nel programma e la definizione dell'ambito namespace non deve contenere un iniziatore .

+0

ma in C++ 03 le costanti statiche intere vanno bene se dichiarate e definite nell'intestazione, come nelle domande –

+0

. Stanno bene se si usano solo i loro valori. L'operatore triadico produce un riferimento a uno dei due valori, che non è possibile quando non sono definiti. Si ottiene un effetto simile se si tenta di passare uno dei valori facendo riferimento a una funzione. –

+0

Quindi perché non sono gli altri compilatori popolari a farlo? Se l'operatore triadico lo fa, non dovrebbe fallire anche su VC2010? –

0

Prova definire questi membri:

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

Fuori dalla dichiarazione di classe.

Foo::FOOBAR = 10; 
Foo::BARFOO = 20; 
Problemi correlati