클래스 정적 변수는 헤더에서 선언 할 수 있지만 .cpp 파일에서 정의 해야 합니다. 정적 변수의 인스턴스는 하나만있을 수 있고 컴파일러는 생성 할 객체 파일을 결정할 수 없으므로 대신 결정을 내려야합니다.
C ++ 11의 선언으로 정적 값의 정의를 유지하기 위해 중첩 된 정적 구조를 사용할 수 있습니다. 이 경우 정적 멤버는 구조이며 .cpp 파일에 정의되어야하지만 값은 헤더에 있습니다.
class A
{
private:
static struct _Shapes {
const std::string RECTANGLE {"rectangle"};
const std::string CIRCLE {"circle"};
} shape;
};
개별 멤버를 초기화하는 대신 전체 정적 구조가 .cpp로 초기화됩니다.
A::_Shapes A::shape;
값은
A::shape.RECTANGLE;
또는-회원은 비공개이며 A에서만 사용할 수 있으므로
shape.RECTANGLE;
이 솔루션은 여전히 정적 변수의 초기화 순서 문제가 있습니다. 정적 값을 사용하여 다른 정적 변수를 초기화하면 첫 번째 변수는 아직 초기화되지 않을 수 있습니다.
// 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 };
이 경우 정적 변수 헤더 에는 링커에서 만든 초기화 순서에 따라 { ""} 또는 { ".h", ".hpp"}가 포함됩니다.
@ abyss.7에서 언급했듯이 constexpr
변수 값을 컴파일 타임에 계산할 수있는 경우 에도 사용할 수 있습니다. 그러나 문자열을 선언 static constexpr const char*
하고 프로그램에서 std::string
달리 std::string
사용하면 상수를 사용할 때마다 새 객체가 생성 되므로 오버 헤드 가 발생합니다.
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.
}