Constructor chuyển đổi (Converting Constructor) là constructor chỉ nhận một tham số (hoặc tất cả tham số sau tham số đầu có giá trị mặc định). Nó cho phép chuyển đổi ngầm (implicit conversion) từ kiểu tham số sang kiểu lớp.
Đặc điểm
- Constructor có 1 tham số (hoặc n tham số nhưng n-1 có default)
- Không phải constructor copy/move
- Cho phép implicit conversion:
MyClass obj = value; - Có thể ngăn chặn bằng
explicit(C++11)
Ví dụ cơ bản
#include <iostream>
class MyClass {
private:
int value;
public:
// Converting constructor
MyClass(int x) : value(x) {
std::cout << "Constructor goi voi: " << x << '\n';
}
void display() const {
std::cout << "value = " << value << '\n';
}
};
int main() {
MyClass obj(10); // Gọi trực tiếp
obj.display(); // value = 10
obj = 50; // IMPLICIT CONVERSION: int -> MyClass
// Tạo temporary MyClass(50), rồi move/assign
obj.display(); // value = 50
}
Kết quả
Constructor goi voi: 10 value = 10 Constructor goi voi: 50 value = 50
Ngăn chặn implicit conversion: explicit
class MyClass {
public:
explicit MyClass(int x) : value(x) {} // C++11: explicit
// ...
};
int main() {
MyClass obj(10); // OK: direct initialization
// obj = 50; // LỖI: implicit conversion bị cấm
obj = MyClass(50); // OK: explicit construction
}
Quy tắc implicit conversion
| Code | Có converting constructor? | Kết quả |
|---|---|---|
MyClass obj = 10; | Có | OK (copy initialization) |
MyClass obj(10); | Có/Không | OK (direct initialization) |
func(10); (void func(MyClass)) | Có | OK (implicit conversion) |
func(10); | Có + explicit | LỖI |
return 10; (MyClass func()) | Có | OK |
Constructor chuyển đổi đa tham số (C++11)
class Point {
int x, y;
public:
// Tất cả tham số sau đều có default -> converting constructor
Point(int x, int y = 0, int z = 0) : x(x), y(y) {}
};
Point p = 5; // OK: Point(5, 0, 0)
Point p2 = {1,2}; // OK: aggregate initialization (không qua constructor này)
C++11: explicit cho conversion operator
class Wrapper {
int value;
public:
Wrapper(int v) : value(v) {}
// Conversion operator ngầm
operator int() const { return value; }
// C++11: explicit conversion operator
explicit operator bool() const { return value != 0; }
};
int main() {
Wrapper w(42);
int x = w; // OK: implicit int conversion
if (w) { } // OK: explicit bool conversion trong context boolean
// bool b = w; // LỖI: explicit bool không chuyển ngầm sang bool variable
}
Best Practice
Mặc định dùngexplicitcho mọi constructor 1 tham số. Chỉ bỏexplicitkhi chuyển đổi ngầm thực sự hợp lý về mặt ngữ nghĩa (ví dụ: wrapper type).
Tóm tắt
- Converting constructor: 1 tham số (hoặc các tham số sau có default)
- Cho phép implicit conversion từ kiểu tham số sang kiểu lớp
- Dùng
explicitđể ngăn chặn (khuyến nghị mặc định) - C++11:
explicitcũng áp dụng cho conversion operator