Trước C ++ 11, chúng ta chỉ có thể thực hiện khởi tạo trong lớp trên các thành viên const tĩnh của kiểu tích phân hoặc kiểu liệt kê. Stroustrup thảo luận về điều này trong Câu hỏi thường gặp về C ++ của mình , đưa ra ví dụ sau:
class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error: not integral
};
Và lý do sau:
Vậy tại sao lại tồn tại những hạn chế bất tiện này? Một lớp thường được khai báo trong tệp tiêu đề và tệp tiêu đề thường được đưa vào nhiều đơn vị dịch. Tuy nhiên, để tránh các quy tắc trình liên kết phức tạp, C ++ yêu cầu mọi đối tượng phải có một định nghĩa duy nhất. Quy tắc đó sẽ bị phá vỡ nếu C ++ cho phép định nghĩa trong lớp của các thực thể cần được lưu trữ trong bộ nhớ dưới dạng đối tượng.
Tuy nhiên, C ++ 11 nới lỏng những hạn chế này, cho phép khởi tạo trong lớp các thành viên không tĩnh (§12.6.2 / 8):
Trong một phương thức khởi tạo không ủy quyền, nếu một thành viên hoặc lớp cơ sở dữ liệu không tĩnh nhất định không được chỉ định bởi một id bộ khởi tạo mem (bao gồm cả trường hợp không có danh sách bộ khởi tạo ghi nhớ vì hàm tạo không có bộ khởi tạo ctor ) và thực thể không phải là một lớp cơ sở ảo của một lớp trừu tượng (10.4), thì
- nếu thực thể là thành viên dữ liệu không tĩnh có bộ khởi tạo dấu ngoặc nhọn hoặc dấu bằng , thì thực thể được khởi tạo như quy định trong 8.5;
- ngược lại, nếu thực thể là một thành viên biến thể (9.5), thì không có quá trình khởi tạo nào được thực hiện;
- nếu không, thực thể được khởi tạo mặc định (8.5).
Phần 9.4.2 cũng cho phép khởi tạo trong lớp các thành viên tĩnh không phải const nếu chúng được đánh dấu bằng mã constexpr
xác định.
Vì vậy, điều gì đã xảy ra với những lý do cho những hạn chế mà chúng ta có trong C ++ 03? Chúng tôi chỉ đơn giản chấp nhận "các quy tắc trình liên kết phức tạp" hay đã thay đổi điều gì khác để làm cho việc này dễ thực hiện hơn?