Câu trả lời:
Bất cứ nơi nào trong một đơn vị biên dịch (thường là tệp .cpp) sẽ làm:
foo.h
class foo {
static const string s; // Can never be initialized here.
static const char* cs; // Same with C strings.
static const int i = 3; // Integral types can be initialized here (*)...
static const int j; // ... OR in cpp.
};
foo.cpp
#include "foo.h"
const string foo::s = "foo string";
const char* foo::cs = "foo C string";
// No definition for i. (*)
const int foo::j = 4;
(*) Theo các tiêu chuẩn bạn phải xác định i
bên ngoài định nghĩa lớp (giống như j
) nếu nó được sử dụng trong mã khác với chỉ các biểu thức hằng tích phân. Xem bình luận của David dưới đây để biết chi tiết.
i
sẽ phải được xác định duy nhất nếu nó được sử dụng ở một nơi khác hơn trong các biểu thức hằng số tích phân, phải không? Trong trường hợp này, bạn không thể nói rằng có lỗi vì không có đủ ngữ cảnh để chắc chắn - hoặc nói một cách nghiêm túc ví dụ trên là chính xác nếu không có mã nào khác. Bây giờ tôi đánh giá cao nhận xét của bạn (+1), tôi vẫn đang tự học mọi thứ! Vì vậy, tôi sẽ cố gắng và làm rõ điểm đó trong câu trả lời, xin vui lòng cho tôi biết nếu nó tốt hơn ...
int f() { return 42; } class foo { static const int i = f(); /* Error! */ }
Lưu ý rằng C ++ 11 cho phép gọi các hàm 'constexpr':constexpr int f() { return 42; } class foo { static const int i = f(); /* Ok */ }
Các thành viên tĩnh cần được khởi tạo trong một đơn vị dịch .cpp ở phạm vi tệp hoặc trong không gian tên thích hợp:
const string foo::s( "my foo");
Trong một đơn vị dịch trong cùng một không gian tên, thường ở trên cùng:
// foo.h
struct foo
{
static const std::string s;
};
// foo.cpp
const std::string foo::s = "thingadongdong"; // this is where it lives
// bar.h
namespace baz
{
struct bar
{
static const float f;
};
}
// bar.cpp
namespace baz
{
const float bar::f = 3.1415926535;
}
Chỉ các giá trị tích phân (ví dụ static const int ARRAYSIZE
:) được khởi tạo trong tệp tiêu đề vì chúng thường được sử dụng trong tiêu đề lớp để xác định một cái gì đó như kích thước của một mảng. Các giá trị không tách rời được khởi tạo trong tệp thực hiện.
i
phải được xác định trong cpp. §9.4.2 / 4 Nếu một thành viên dữ liệu tĩnh thuộc kiểu liệt kê const hoặc tích phân const, khai báo của nó trong định nghĩa lớp có thể chỉ định một bộ khởi tạo hằng sẽ là biểu thức hằng tích phân (5.19). Trong trường hợp đó, thành viên có thể xuất hiện trong các biểu thức hằng số tích phân. Thành viên vẫn sẽ được xác định trong phạm vi không gian tên nếu nó được sử dụng trong chương trình và định nghĩa phạm vi không gian tên sẽ không chứa bộ khởi tạo.