C ++ onde inicializar const estático

129

Eu tenho aula

class foo {
public:
   foo();
   foo( int );
private:
   static const string s;
};

Onde é o melhor lugar para inicializar a string sno arquivo de origem?

Thomas
fonte

Respostas:

178

Em qualquer lugar em uma unidade de compilação (geralmente um arquivo .cpp):

foo.h

class foo {
    static const string s; // Can never be initialized here.
    static const char* cs; // Same with C strings.

    static const int i = 3; // Integral types can be initialized here (*)...
    static const int j; //     ... OR in cpp.
};

foo.cpp

#include "foo.h"
const string foo::s = "foo string";
const char* foo::cs = "foo C string";
// No definition for i. (*)
const int foo::j = 4;

(*) De acordo com os padrões, você deve definir ifora da definição de classe (como jé) se ela for usada em código que não seja apenas expressões constantes integrais. Veja o comentário de David abaixo para detalhes.

esqueleto
fonte
27
Voto a favor, mas depois de revisar o padrão, há um erro no seu código: ideve ser definido no cpp. §9.4.2 / 4 Se um membro de dados estáticos for do tipo const integral ou de enumeração const, sua declaração na definição de classe pode especificar um inicializador constante que deve ser uma expressão constante integral (5.19). Nesse caso, o membro pode aparecer em expressões constantes integrais. O membro ainda deve ser definido em um escopo de espaço para nome, se for usado no programa e a definição do escopo de espaço para nome não deve conter um inicializador.
David Rodríguez - dribeas
3
Com base na sua cotação das normas, parece iteria que ser ser definido unicamente se ele foi usado em algum outro lugar do que em expressões constantes integrais, certo? Nesse caso, você não pode dizer que há um erro porque não há contexto suficiente para ter certeza - ou, estritamente falando, o exemplo acima está correto se não houver outro código. Agora eu aprecio o seu comentário (+1), ainda estou aprendendo as coisas! Então, eu vou tentar esclarecer esse ponto na resposta, por favor, deixe-me saber se é melhor ...
squelart
@squelart Desculpe se pareço idiota, mas um exemplo de declaração diferente da expressão constante integral seria?
21413 Saksham
3
@Saksham Por exemplo, chamar uma função, por exemplo: int f() { return 42; } class foo { static const int i = f(); /* Error! */ }Observe que o C ++ 11 permite chamar funções 'constexpr':constexpr int f() { return 42; } class foo { static const int i = f(); /* Ok */ }
squelart
@squelart Eu li o texto de tal forma que a definição deve ser fornecida se o membro for utilizado - a redação da norma não limita esse requisito a expressões constantes integrais.
VladLosev
12

Os membros estáticos precisam ser inicializados em uma unidade de tradução .cpp no ​​escopo do arquivo ou no espaço para nome apropriado:

const string foo::s( "my foo");
Michael Burr
fonte
11

Em uma unidade de tradução dentro do mesmo espaço para nome, geralmente na parte superior:

// foo.h
struct foo
{
    static const std::string s;
};

// foo.cpp
const std::string foo::s = "thingadongdong"; // this is where it lives

// bar.h
namespace baz
{
    struct bar
    {
        static const float f;
    };
}

// bar.cpp
namespace baz
{
    const float bar::f = 3.1415926535;
}
GManNickG
fonte
8

Desde C ++ 17, o especificador em linha também se aplica a variáveis. Agora você pode definir variáveis ​​de membro estáticas na definição de classe:

#include <string>

class foo {
public:
   foo();
   foo( int );
private:
   inline static const std::string s { "foo" };
};
plexando
fonte
1

Somente valores integrais (por exemplo, static const int ARRAYSIZE) são inicializados no arquivo de cabeçalho porque geralmente são usados ​​no cabeçalho da classe para definir algo como o tamanho de uma matriz. Valores não integrais são inicializados no arquivo de implementação.

Behnam Dezfouli
fonte