C++构造与析构(17) - virtual拷贝构造函数

来源:互联网 发布:linux vi中搜索字符串 编辑:程序博客网 时间:2024/05/26 05:51
在上一篇文章中介绍了实现"virtual constructor"的方法。点击此链接。
有没有可能在不知道类的类型的情形下创建一个对象?

众所周知,拷贝构造函数是用一个已经存在的对象,来构造一个新的对象。新对象的初始状态取决于已存在对象的状态。当使用一个对象初始化另一个对象时,编译器会调用拷贝构造函数。但是,编译器需要知道确切的类型信息才能调用拷贝构造函数。

#include <iostream>using 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;}
如果用户无法确定对象的类型,此时如何使用拷贝构造函数?例如virtual constructor在运行时期间创建了一个对象。当使用拷贝构造函数创建对象时,如果已存在对象是virtual constructor创建的,我们无法使用拷贝构造函数。需要自定义一个在运行时可以拷贝对象的函数。

假设存在这样的例子,一个绘图程序。它支持从已有的图案进行拷贝-粘贴。从程序员的角度看,我们无法知道哪个图案会被拷贝-粘贴,因为它是一个运行时的行为。在这种情况下,就需要使用virtual copy constructor来帮助。

类似地,对于一个记录板程序,从已存在对象拷贝,然后粘贴。具体对象类型是运行时的行为,无法提前知道。就需要使用virtual copy constructor了。参见下面例子:

#include <iostream>using namespace std; //// LIBRARY SRARTclass Base{public:    Base() { }     virtual ~Base() { }  // 确保调用子类析构函数    virtual void ChangeAttributes() = 0;     // 做为"Virtual Constructor"    static Base *Create(int id);     // 做为"Virtual Copy Constructor"    virtual Base *Clone() = 0;}; 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;    }}//// LIBRARY END 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;}
User类使用virtual constructor创建一个对象。这个对象取决于user input。 函数Action()会拷贝已存在对象给新对象,并修改新对象的属性。使用虚函数Clone()来创建新对象的过程,即被称为virtual copy constructor. 这里使用Clone()方法的这种概念,就属于设计模式中的"原型模式prototype pattern".

0 0
原创粉丝点击