Zmienne statyczne klasy można zadeklarować w nagłówku, ale muszą być zdefiniowane w pliku .cpp. Wynika to z faktu, że może istnieć tylko jedna instancja zmiennej statycznej, a kompilator nie może zdecydować, w którym wygenerowanym pliku obiektowym go umieścić, więc musisz podjąć decyzję.
Aby zachować definicję wartości statycznej z deklaracją w C ++ 11, można użyć zagnieżdżonej struktury statycznej. W takim przypadku element statyczny jest strukturą i musi zostać zdefiniowany w pliku .cpp, ale wartości znajdują się w nagłówku.
class A
{
private:
static struct _Shapes {
const std::string RECTANGLE {"rectangle"};
const std::string CIRCLE {"circle"};
} shape;
};
Zamiast inicjowania poszczególnych elementów cała struktura statyczna jest inicjowana w .cpp:
A::_Shapes A::shape;
Dostęp do wartości można uzyskać za pomocą
A::shape.RECTANGLE;
lub - ponieważ członkowie są prywatni i mają być używane tylko z A - z
shape.RECTANGLE;
Zauważ, że w tym rozwiązaniu nadal występuje problem kolejności inicjalizacji zmiennych statycznych. Gdy wartość statyczna jest używana do inicjalizacji innej zmiennej statycznej, pierwsza może jeszcze nie zostać zainicjowana.
// 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 };
W takim przypadku nagłówki zmiennych statycznych będą zawierać {""} lub {".h", ".hpp"}, w zależności od kolejności inicjowania utworzonej przez linker.
Jak wspomniano w @ abyss.7, można również użyć, constexpr
jeśli wartość zmiennej można obliczyć w czasie kompilacji. Ale jeśli zadeklarujesz swoje ciągi, static constexpr const char*
a twój program użyje std::string
inaczej, powstanie narzut, ponieważ nowy std::string
obiekt będzie tworzony za każdym razem, gdy użyjesz takiej stałej:
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.
}