C++ không hỗ trợ constructor ảo, nhưng có thể mô phỏng bằng idiom Virtual Copy Constructor (hay còn gọi là Clone Pattern) sử dụng hàm ảo clone().
Vấn đề: Cần tạo bản sao đối tượng khi chỉ biết kiểu cơ sở (base class) tại runtime.
Giải pháp:
- Base class khai báo pure virtual
clone()trả về con trỏ base. - Derived class override
clone()trả vềnew Derived(*this). - Sử dụng:
Base* copy = obj->clone();
Thường kết hợp với create() static factory method.
Ví dụ minh họa (Hình học)
#include <iostream>
using namespace std;
class Figure {
public:
virtual ~Figure() {}
virtual void changeAttributes() = 0;
static Figure* create(int id);
virtual Figure* clone() = 0;
};
class Square : public Figure {
public:
Square() { cout << "Square created\n"; }
void changeAttributes() override {
int a; cout << "Canh vuong: "; cin >> a;
cout << "Dien tich: " << a*a << endl;
}
Figure* clone() override { return new Square(*this); }
};
class Circle : public Figure {
public:
Circle() { cout << "Circle created\n"; }
void changeAttributes() override {
int r; cout << "Ban kinh: "; cin >> r;
cout << "Dien tich: " << 3.14*r*r << endl;
}
Figure* clone() override { return new Circle(*this); }
};
class Rectangle : public Figure {
public:
Rectangle() { cout << "Rectangle created\n"; }
void changeAttributes() override {
int a,b; cout << "Canh hcn: "; cin >> a >> b;
cout << "Dien tich: " << a*b << endl;
}
Figure* clone() override { return new Rectangle(*this); }
};
Figure* Figure::create(int id) {
if (id == 1) return new Square;
if (id == 2) return new Circle;
return new Rectangle;
}
class User {
Figure* fig;
public:
User() {
int input;
cout << "Chon hinh (1-Vuong, 2-Tron, 3-HCN): ";
cin >> input;
fig = Figure::create(input);
}
~User() { delete fig; }
void action() {
Figure* f = fig->clone();
f->changeAttributes();
delete f;
}
};
int main() {
User u;
u.action();
return 0;
}
Kết quả (ví dụ chọn 2)
Chon hinh (1-Vuong, 2-Tron, 3-HCN): 2 Circle created Ban kinh: 3 Dien tich: 28.26