博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++构造与析构(17) - virtual拷贝构造函数
阅读量:4071 次
发布时间:2019-05-25

本文共 3658 字,大约阅读时间需要 12 分钟。

在上一篇文章中介绍了实现"virtual构造函数"的方法--。

有没有可能在不知道类的具体类型的情况下创建一个对象?

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

#include 
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;}

运行结果:

Derived created
Derived created by deep copy
Derived destroyed
Derived destroyed

如果用户无法确定对象的类型,此时如何使用拷贝构造函数?例如在运行时期间创建了一个对象。当使用拷贝构造函数创建对象时,如果已存在对象是virtual构造函数创建的,我们无法使用拷贝构造函数。需要自定义一个在运行时可以拷贝对象的函数。

举例说明:有一个绘图程序,它支持从已有的图案进行拷贝-粘贴。

从程序员的角度看,我们无法知道哪个图案会被拷贝-粘贴,因为它是一个运行时的行为。在这种情况下,就需要使用virtual拷贝构造函数来帮助。

类似地,对于一个记录板程序,从已存在对象拷贝,然后粘贴。具体对象类型是运行时的行为,无法提前知道。就需要使用virtual拷贝构造函数了。

参见下面例子:

#include 
using 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 destroyed

User类使用virtual constructor创建一个对象。这个对象取决于用户输入值input ID。

函数Action()会拷贝已存在对象给新对象,并修改新对象的属性。使用虚函数Clone()来创建新对象的过程,即被称为virtual copy constructor。
这里使用Clone()方法的这种概念,就属于设计模式中的 原型模式prototype pattern。具体可参考本人的这篇文章 。

 

转载地址:http://gqeji.baihongyu.com/

你可能感兴趣的文章
分布式缓存负载均衡负载均衡的缓存处理:虚拟节点对一致性hash的改进
查看>>
分布式存储系统设计(1)—— 系统架构
查看>>
MySQL数据库的高可用方案总结
查看>>
常用排序算法总结(一) 比较算法总结
查看>>
SSH原理与运用
查看>>
SIGN UP BEC2
查看>>
S3C2440中对LED驱动电路的理解
查看>>
《天亮了》韩红
查看>>
Windows CE下USB摄像头驱动开发(以OV511为例,附带全部源代码以及讲解) [转]
查看>>
出现( linker command failed with exit code 1)错误总结
查看>>
iOS开发中一些常见的并行处理
查看>>
iOS获取手机的Mac地址
查看>>
ios7.1发布企业证书测试包的问题
查看>>
如何自定义iOS中的控件
查看>>
iOS 开发百问
查看>>
Mac环境下svn的使用
查看>>
github简单使用教程
查看>>
如何高效利用GitHub
查看>>
环境分支-git版本管理
查看>>
uni-app 全局变量
查看>>