Les variables statiques de classe peuvent être déclarées dans l'en-tête mais doivent être définies dans un fichier .cpp. En effet, il ne peut y avoir qu'une seule instance d'une variable statique et le compilateur ne peut pas décider dans quel fichier objet généré le placer, vous devez donc prendre la décision à la place.
Pour conserver la définition d'une valeur statique avec la déclaration en C ++ 11, une structure statique imbriquée peut être utilisée. Dans ce cas, le membre statique est une structure et doit être défini dans un fichier .cpp, mais les valeurs sont dans l'en-tête.
class A
{
private:
static struct _Shapes {
const std::string RECTANGLE {"rectangle"};
const std::string CIRCLE {"circle"};
} shape;
};
Au lieu d'initialiser des membres individuels, toute la structure statique est initialisée en .cpp:
A::_Shapes A::shape;
Les valeurs sont accessibles avec
A::shape.RECTANGLE;
ou - puisque les membres sont privés et sont destinés à être utilisés uniquement à partir de A - avec
shape.RECTANGLE;
Notez que cette solution souffre toujours du problème de l'ordre d'initialisation des variables statiques. Lorsqu'une valeur statique est utilisée pour initialiser une autre variable statique, la première peut ne pas encore être initialisée.
// 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 };
Dans ce cas, la variable statique têtes des contiendront {""} ou {".h", ".hpp"}, selon l'ordre d'initialisation créé par l'éditeur de liens.
Comme mentionné par @ abyss.7, vous pouvez également utiliser constexpr
si la valeur de la variable peut être calculée au moment de la compilation. Mais si vous déclarez vos chaînes avec static constexpr const char*
et que votre programme utilise std::string
autrement, il y aura une surcharge car un nouvel std::string
objet sera créé chaque fois que vous utiliserez une telle constante:
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.
}