Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Constructor chuyển đổi (Converting Constructor) trong C++

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

CodeCó converting constructor?Kết quả
MyClass obj = 10;CóOK (copy initialization)
MyClass obj(10);Có/KhôngOK (direct initialization)
func(10); (void func(MyClass))CóOK (implicit conversion)
func(10);Có + explicitLỖ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ùng explicit cho mọi constructor 1 tham số. Chỉ bỏ explicit khi 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: explicit cũng áp dụng cho conversion operator