Trong C++, các thành viên dữ liệu const bắt buộc phải được khởi tạo trong danh sách khởi tạo (member initializer list) của constructor. Không thể gán giá trị trong thân hàm constructor.
Cú pháp
class MyClass {
const int x; // Thành viên const
public:
MyClass(int a) : x(a) { // Khởi tạo trong initializer list
// Thân constructor - KHÔNG thể gán x = a ở đây
}
};
Ví dụ hoàn chỉnh
#include <iostream>
using namespace std;
class MyClass {
private:
const int x; // Hằng thành viên
public:
// Constructor với initializer list
MyClass(int a) : x(a) {
// x = a; // LỖI: Không thể gán cho const member ở đây
}
void show_x() const {
cout << "Gia tri hang x: " << x << endl;
}
};
int main() {
MyClass obj(40);
obj.show_x();
}
Kết quả
Gia tri hang x: 40
Tại sao phải dùng initializer list?
constmember không thể gán sau khi khởi tạo- Tham chiếu (
int& ref) cũng bắt buộc khởi tạo ở đây - Lớp cơ sở (base class) và thành viên không có constructor mặc định
- Hiệu năng: Tránh default-construct rồi gán lại
Nhiều thành viên const
class Example {
const int a;
const double b;
const string& ref; // Tham chiếu const
public:
Example(int ia, double db, const string& str)
: a(ia), b(db), ref(str) // Phân tách bằng dấu phẩy
{}
};
Lỗi thường gặp
class Bad {
const int x;
public:
Bad(int val) {
x = val; // LỖI BIÊN DỊCH: assignment of read-only member
}
};
Thứ tự khởi tạo
Thành viên được khởi tạo theo thứ tự khai báo trong class, không phải thứ tự trong initializer list. Nên viết initializer list theo thứ tự khai báo để tránh nhầm lẫn.
class Order {
int first;
int second;
public:
Order() : second(10), first(second + 5) {} // CẢNH BÁO: first khởi tạo trước second!
// first = 5 (rác), second = 10
};
Tóm tắt
constmember → bắt buộc initializer list- Tham chiếu member → bắt buộc initializer list
- Thứ tự khởi tạo = thứ tự khai báo trong class
- Dùng initializer list cho tất cả member để nhất quán và hiệu năng