Các biến tĩnh lớp có thể được khai báo trong tiêu đề nhưng phải được định nghĩa trong tệp .cpp. Điều này là do chỉ có thể có một phiên bản của biến tĩnh và trình biên dịch không thể quyết định tệp đối tượng được tạo để đặt nó để bạn phải đưa ra quyết định, thay vào đó.
Để giữ định nghĩa của một giá trị tĩnh với khai báo trong C ++ 11, có thể sử dụng cấu trúc tĩnh lồng nhau. Trong trường hợp này, thành viên tĩnh là một cấu trúc và phải được xác định trong tệp .cpp, nhưng các giá trị nằm trong tiêu đề.
class A
{
private:
static struct _Shapes {
const std::string RECTANGLE {"rectangle"};
const std::string CIRCLE {"circle"};
} shape;
};
Thay vì khởi tạo các thành viên riêng lẻ, toàn bộ cấu trúc tĩnh được khởi tạo trong .cpp:
A::_Shapes A::shape;
Các giá trị được truy cập với
A::shape.RECTANGLE;
hoặc - vì các thành viên là riêng tư và chỉ được sử dụng từ A - với
shape.RECTANGLE;
Lưu ý rằng giải pháp này vẫn gặp phải vấn đề về thứ tự khởi tạo các biến tĩnh. Khi một giá trị tĩnh được sử dụng để khởi tạo một biến tĩnh khác, đầu tiên có thể chưa được khởi tạo.
// 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 };
Trong trường hợp này, các tiêu đề biến tĩnh sẽ chứa {""} hoặc {".h", ".hpp"}, tùy thuộc vào thứ tự khởi tạo được tạo bởi trình liên kết.
Như được đề cập bởi @ abyss.7, bạn cũng có thể sử dụng constexpr
nếu giá trị của biến có thể được tính toán tại thời điểm biên dịch. Nhưng nếu bạn khai báo các chuỗi của mình static constexpr const char*
và chương trình của bạn sử dụng std::string
nếu không sẽ có một chi phí vì một std::string
đối tượng mới sẽ được tạo mỗi khi bạn sử dụng hằng số như vậy:
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.
}