C ++ inicializa variables ​​estáticas na class?

Tenho notado que algumas das minhas funções em uma class não estão acessando o object, então as tornei static . Então o compilador me disse que todas as variables ​​que eles acessam também devem ser estáticas – bem, bastante compreensíveis até agora. Eu tenho um monte de variables ​​de string, como

 string RE_ANY = "([^\\n]*)"; string RE_ANY_RELUCTANT = "([^\\n]*?)"; 

e assim por diante na class. Eu fiz então todos eles static const porque eles nunca mudam. No entanto, meu programa só compila se eu movê-los para fora da class: Caso contrário, o MSVC ++ 2010 reclama “Somente variables ​​integrais de constante estática podem ser inicializadas dentro de uma class”.

Bem, isso é lamentável. Existe uma solução alternativa? Eu gostaria de deixá-los dentro da class a que pertencem.

Eles não podem ser inicializados dentro da class, mas podem ser inicializados fora da class, em um arquivo de origem:

 // inside the class class Thing { static string RE_ANY; static string RE_ANY_RELUCTANT; }; // in the source file string Thing::RE_ANY = "([^\\n]*)"; string Thing::RE_ANY_RELUCTANT = "([^\\n]*?)"; 

Atualizar

Acabei de notar a primeira linha da sua pergunta – você não quer tornar essas funções static , você quer torná-las const . Torná-los static significa que eles não estão mais associados a um object (portanto, não podem acessar nenhum membro não-estático) e tornar os dados estáticos significa que eles serão compartilhados com todos os objects desse tipo. Isso pode não ser o que você quer. Fazê-los const simplesmente significa que eles não podem modificar nenhum membro, mas ainda podem acessá-los.

Mike Seymour deu a resposta certa, mas para adicionar …
C ++ permite que você declare e defina em seu corpo de class apenas tipos integrais static const , como o compilador informa. Então você pode realmente fazer:

 class Foo { static const int someInt = 1; static const short someShort = 2; // etc. }; 

E você não pode fazer isso com qualquer outro tipo, nesse caso você deve defini-los em seu arquivo .cpp.

Variáveis ​​de membro estático devem ser declaradas na class e, em seguida, definidas fora dela!

Não há solução alternativa, basta colocar sua definição real em um arquivo de origem.


De sua descrição, cheira como se você não estivesse usando variables ​​estáticas da maneira certa. Se eles nunca mudarem, você deve usar a variável constante, mas sua descrição é muito genérica para dizer algo mais.

As variables ​​de membro estático sempre mantêm o mesmo valor para qualquer instância de sua class: se você alterar uma variável estática de um object, ela também será alterada para todos os outros objects (e, na verdade, também é possível acessá-los sem uma ocorrência da class) ie: um object).

Desde C ++ 11, pode ser feito dentro de uma class com constexpr .

 class stat { public: // init inside class static constexpr double inlineStaticVar = 22; }; 

A variável agora pode ser acessada com:

 stat::inlineStaticVar 

Eu sinto que vale a pena acrescentar que uma variável estática não é a mesma que uma variável constante.

usando uma variável constante em uma class

 struct Foo{ const int a; Foo(int b) : a(b){} } 

e nós declará-lo como assim

 fooA = new Foo(5); fooB = new Foo(10); // fooA.a = 5; // fooB.a = 10; 

Para uma variável estática

 struct Bar{ static int a; Foo(int b){ a = b; } } Bar::a = 0; // set value for a 

que é usado assim

 barA = new Bar(5); barB = new Bar(10); // barA.a = 10; // barB.a = 10; // Bar::a = 10; 

Você vê o que acontece aqui. A variável constante, que é instanciada junto com cada instância de Foo, como Foo é instanciado, tem um valor separado para cada instância de Foo, e não pode ser alterada por Foo.

Onde como com Bar, o seu é apenas um valor para Bar :: a não importa quantas instâncias de Bar são feitas. Todos eles compartilham esse valor, você também pode acessá-lo com qualquer instância de Bar. A variável estática também segue as regras para public / private, então você pode fazer com que apenas instâncias de Bar possam ler o valor de Bar :: a;

Apenas para adicionar em cima das outras respostas. Para inicializar um membro estático complexo , você pode fazer isso da seguinte maneira:

Declare seu membro estático como de costume.

 // myClass.h class myClass { static complexClass s_complex; //... }; 

Faça uma pequena function para inicializar sua turma se não for trivial fazê-lo. Isso será chamado apenas uma vez que o membro estático é inicializado. (Note que o construtor de cópia do complexClass será usado, então deve estar bem definido).

 //class.cpp #include myClass.h complexClass initFunction() { complexClass c; c.add(...); c.compute(...); c.sort(...); // Etc. return c; } complexClass myClass::s_complex = initFunction(); 

Se o seu objective é inicializar a variável estática no seu arquivo de header (em vez de um arquivo * .cpp, o que você pode querer se estiver aderindo a um idioma “somente header”), então você pode contornar o problema de boot usando um modelo. Variáveis ​​estáticas modeladas podem ser inicializadas em um header, sem causar múltiplos símbolos a serem definidos.

Veja aqui um exemplo:

Inicialização de membro estático em um modelo de class

Opcionalmente, mova todas as constantes para o arquivo .cpp sem declaração no arquivo .h. Use namespace anônimo para torná-los invisíveis além do módulo cpp.

 // MyClass.cpp #include "MyClass.h" // anonymous namespace namespace { string RE_ANY = "([^\\n]*)"; string RE_ANY_RELUCTANT = "([^\\n]*?)"; } // member function (static or not) bool MyClass::foo() { // logic that uses constants return RE_ANY_RELUCTANT.size() > 0; } 

Algumas respostas parecem estar enganando um pouco.

Você não precisa

  • Atribuir um valor ao object estático ao inicializar, atribuir um valor é Opcional .
  • Crie outro arquivo .cpp para inicializá-lo. Isso pode ser feito da mesma forma no arquivo de header .

 #ifndef CLASS_A_H #define CLASS_A_H #include  class A { private: static std::string str; static int x; }; // Initialize with no values std::string A::str; int A::x; // Initialize with values //std::string A::str = "SO!"; //int A::x = 900; #endif