Respostas:
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 i
fora 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.
i
teria 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 ...
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 */ }
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");
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;
}
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.
i
deve 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.