本文共 3658 字,大约阅读时间需要 12 分钟。
在上一篇文章中介绍了实现"virtual构造函数"的方法--。
有没有可能在不知道类的具体类型的情况下创建一个对象?
众所周知,拷贝构造函数是用一个已经存在的对象,来构造一个新的对象。新对象的初始状态取决于已存在对象的状态。当使用一个对象初始化另一个对象时,编译器会调用拷贝构造函数。但是,编译器需要知道确切的类型信息才能调用拷贝构造函数。
#includeusing namespace std;class Base {public:};class Derived : public Base {public: Derived() { cout << "Derived created" << endl; } Derived(const Derived& rhs) { cout << "Derived created by deep copy" << endl; } ~Derived() { cout << "Derived destroyed" << endl; }};int main() { Derived s1; Derived s2 = s1; // 编译器会调用拷贝构造函数 // s1和s2的类型对于编译器是具体的/确切知道的。 // 基于基类指针或引用(指向的是子类对象),如何创建Derived1或Derived2对象? return 0;}
运行结果:
Derived created Derived created by deep copy Derived destroyed Derived destroyed如果用户无法确定对象的类型,此时如何使用拷贝构造函数?例如在运行时期间创建了一个对象。当使用拷贝构造函数创建对象时,如果已存在对象是virtual构造函数创建的,我们无法使用拷贝构造函数。需要自定义一个在运行时可以拷贝对象的函数。
举例说明:有一个绘图程序,它支持从已有的图案进行拷贝-粘贴。
从程序员的角度看,我们无法知道哪个图案会被拷贝-粘贴,因为它是一个运行时的行为。在这种情况下,就需要使用virtual拷贝构造函数来帮助。类似地,对于一个记录板程序,从已存在对象拷贝,然后粘贴。具体对象类型是运行时的行为,无法提前知道。就需要使用virtual拷贝构造函数了。
参见下面例子:#includeusing namespace std;class Base {public: Base() {} virtual ~Base() {} // 确保调用子类析构函数 virtual void ChangeAttributes() = 0; static Base* Create(int id); // 做为"virtual constructor" virtual Base* Clone() = 0; // 做为"virtual copy constructor"};class Derived1 : public Base {public: Derived1() { cout << "Derived1 created" << endl; } Derived1(const Derived1& rhs) { cout << "Derived1 created by deep copy" << endl; } ~Derived1() { cout << "~Derived1 destroyed" << endl; } void ChangeAttributes() { cout << "Derived1 Attributes Changed" << endl; } Base* Clone() { return new Derived1(*this); }};class Derived2 : public Base {public: Derived2() { cout << "Derived2 created" << endl; } Derived2(const Derived2& rhs) { cout << "Derived2 created by deep copy" << endl; } ~Derived2() { cout << "~Derived2 destroyed" << endl; } void ChangeAttributes() {cout << "Derived2 Attributes Changed" << endl; } Base* Clone() { return new Derived2(*this); }};class Derived3 : public Base {public: Derived3() { cout << "Derived3 created" << endl; } Derived3(const Derived3& rhs) { cout << "Derived3 created by deep copy" << endl; } ~Derived3() { cout << "~Derived3 destroyed" << endl; } void ChangeAttributes() { cout << "Derived3 Attributes Changed" << endl; } Base* Clone() { return new Derived3(*this); }};Base* Base::Create(int id) { //如果新的Derived类加入,只需要在此添加if-else. //User类不需要重新编译即可支持新加的对象。 if (id == 1) { return new Derived1; } else if (id == 2) { return new Derived2; } else { return new Derived3; }}class User {public: // 运行时期间创建Base对象 User() : pBase(0) { int input; cout << "Enter ID (1, 2 or 3): "; cin >> input; while ((input != 1) && (input != 2) && (input != 3)) { cout << "Enter ID (1, 2 or 3 only): "; cin >> input; } // 调用"Virtual Constructor"来创建对象 pBase = Base::Create(input); } ~User() { if (pBase) { delete pBase; pBase = 0; } } void Action() { // 赋值当前对象 Base* pNewBase = pBase->Clone(); pNewBase->ChangeAttributes(); delete pNewBase; }private: Base* pBase;};int main() { User* user = new User(); user->Action(); delete user;}
运行结果:
Enter ID (1, 2 or 3): 3 Derived3 created Derived3 created by deep copy Derived3 Attributes Changed ~Derived3 destroyed ~Derived3 destroyedUser类使用virtual constructor创建一个对象。这个对象取决于用户输入值input ID。
函数Action()会拷贝已存在对象给新对象,并修改新对象的属性。使用虚函数Clone()来创建新对象的过程,即被称为virtual copy constructor。这里使用Clone()方法的这种概念,就属于设计模式中的 原型模式prototype pattern。具体可参考本人的这篇文章 。
转载地址:http://gqeji.baihongyu.com/