Статические переменные класса могут быть объявлены в заголовке, но должны быть определены в файле .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;
или - поскольку члены являются частными и предназначены для использования только из А - с
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.
}