2012-09-19 14 views
7

en foo.h:estática constante de la declaración de miembro de la clase

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

en 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 
} 

Estoy compilando con GCC 4.5.3. ¿Hay alguna razón por la cual el enlazador fallaría cuando la línea * 1 está descomentada?

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

Probado con VC2005, 2008, 2010 y CB2010. Todos compilaron y vinculó bien. ¿Por qué GCC falla en este caso?

Dado el answer here, ¿por qué los otros compiladores populares no fallan como GCC? De una manera u otra, tiene que ser un error, ya sea para GCC u otros compiladores populares. ¿O hay una explicación más razonable?

+3

Hmm ... Se compila bien en VS2010. – Mysticial

+0

Compila y enlaces en CB2010 y VS2005 también –

+1

@Mysticial pregunta es sobre gcc sin embargo. y puedo confirmar el error del enlazador. –

Respuesta

4

Formalmente, la cabecera sólo declara las constantes estáticas, y también tienen que ser definido (al menos en C++ 03). Sin embargo, si solo usa sus valores, lo más probable es que se salga con la suya.

En C++ 11 esto se especifica más formalmente como que requiere una definición cuando la estática es "odr-used". La línea *1 es un ejemplo de esto. El operador triádico intenta formar una referencia a los valores, y el compilador (o vinculador en realidad) se da cuenta de que no puede.


El estándar de C++ 11 dice

9.4.2 miembros de datos estáticos
§ 3 ...
El miembro todavía se definirá en un ámbito espacio de nombres si está odr-used (3.2) en el programa y la definición del alcance del espacio de nombres no debe contener inicializador.

+0

pero en C++ 03 entero las constantes estáticas están bien si se declaran y definen en el encabezado, como en las preguntas –

+0

Están bien si solo usa sus valores. El operador triádico produce una referencia a uno de los dos valores, que no es posible cuando no están definidos. Obtiene un efecto similar si intenta pasar uno de los valores por referencia a una función. –

+0

Entonces, ¿por qué los otros compiladores populares no están haciendo eso? Si el operador triádico hace eso, ¿no debería fallar también en VC2010? –

0

Intenta definir estos miembros:

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

Fuera de la declaración de la clase.

Foo::FOOBAR = 10; 
Foo::BARFOO = 20; 
Cuestiones relacionadas