Constructor chuyển đổi là constructor chỉ nhận một đối số (hoặc nhiều đối số nhưng các tham số sau có giá trị mặc định). Nó cho phép chuyển đổi ngầm (implicit conversion) từ kiểu đối số sang kiểu lớp.
Ví dụ cơ bản
#include <iostream>
using namespace std;
class MyClass {
int my_var;
public:
MyClass(int x) : my_var(x) {} // Constructor chuyển đổi
void display() { cout << "my_var = " << my_var << endl; }
};
int main() {
MyClass obj(10); // Gọi trực tiếp
obj.display(); // my_var = 10
obj = 50; // Chuyển đổi ngầm: 50 -> MyClass(50) -> gán
obj.display(); // my_var = 50
return 0;
}
Kết quả
my_var = 10 my_var = 50
Cơ chế
obj = 50;trình biên dịch thấy cầnMyClassnhưng cóint.- Tìm constructor
MyClass(int)– tạo đối tượng tạmMyClass(50). - Gán đối tượng tạm vào
obj(sử dụng operator= mặc định – copy thành viên).
Vấn đề & Giải pháp (C++11)
Chuyển đổi ngầm có thể gây lỗi logic khó phát hiện:
void func(MyClass m); // nhận bằng giá trị func(100); // OK ngầm -> func(MyClass(100)) – có ý không?
Giải pháp: thêm explicit trước constructor:
explicit MyClass(int x) : my_var(x) {}
Khi đó:
MyClass obj(10);✅ (khởi tạo trực tiếp)obj = 50;❌ lỗi compileobj = MyClass(50);✅ (ép kiểu tường minh)func(MyClass(100));✅
Thực hành tốt
- Mặc định khai báo constructor 1 tham số là
explicit. - Chỉ bỏ
explicitkhi chuyển đổi ngầm thực sự tự nhiên và an toàn (ví dụ: wrapper số học, smart pointer). - C++20:
explicit(bool) cho phép điều kiện explicit.