Las variables estáticas de clase se pueden declarar en el encabezado pero se deben definir en un archivo .cpp. Esto se debe a que solo puede haber una instancia de una variable estática y el compilador no puede decidir en qué archivo de objeto generado colocarlo, por lo que debe tomar la decisión.
Para mantener la definición de un valor estático con la declaración en C ++ 11, se puede utilizar una estructura estática anidada. En este caso, el miembro estático es una estructura y debe definirse en un archivo .cpp, pero los valores están en el encabezado.
class A
{
private:
static struct _Shapes {
const std::string RECTANGLE {"rectangle"};
const std::string CIRCLE {"circle"};
} shape;
};
En lugar de inicializar miembros individuales, toda la estructura estática se inicializa en .cpp:
A::_Shapes A::shape;
Se accede a los valores con
A::shape.RECTANGLE;
o - dado que los miembros son privados y están destinados a ser utilizados solo desde A - con
shape.RECTANGLE;
Tenga en cuenta que esta solución aún adolece del problema del orden de inicialización de las variables estáticas. Cuando se usa un valor estático para inicializar otra variable estática, la primera puede no inicializarse todavía.
// file.h
class File {
public:
static struct _Extensions {
const std::string h{ ".h" };
const std::string hpp{ ".hpp" };
const std::string c{ ".c" };
const std::string cpp{ ".cpp" };
} extension;
};
// file.cpp
File::_Extensions File::extension;
// module.cpp
static std::set<std::string> headers{ File::extension.h, File::extension.hpp };
En este caso, los encabezados de las variables estáticas contendrán {""} o {".h", ".hpp"}, según el orden de inicialización creado por el vinculador.
Como mencionó @ abyss.7, también podría usar constexpr
si el valor de la variable se puede calcular en tiempo de compilación. Pero si declara sus cadenas con static constexpr const char*
y su programa usa lo std::string
contrario, habrá una sobrecarga porque se std::string
creará un nuevo objeto cada vez que use una constante de este tipo:
class A {
public:
static constexpr const char* STRING = "some value";
};
void foo(const std::string& bar);
int main() {
foo(A::STRING); // a new std::string is constructed and destroyed.
}