クラス静的変数はヘッダーで宣言できますが、.cppファイルで定義する必要があります。これは、静的変数のインスタンスは1つしか存在できず、コンパイラーはそれを配置するために生成されたオブジェクトファイルを決定できないため、代わりに決定を行う必要があるためです。
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.
}