将一个list的值赋给一个对象_C/C++编程日记:将不同类型的对象放进同一个容器...

前言:不同类型的对象,放进同一个容器。(下文以数组表示容器)

代理类

问题:

现有不同种类的交通工具类派生层次,如下:

986bd32e8078c1450a4da1edb6ece47a.png
classVehicle{public:virtualdoubleweight()const=0;virtualvoidstart()=0;};classAircraft:publicVehicle {};classAutomobile:publicVehicle {};

我们想对一系列不同各类的Vehicle进行管理:

Vehicle parking_lot[1000];

不足:

抽象类不可实例化

若基类不是抽象类,类型转换会带来问题

99c10866951389fd01ed70c2bd64a05e.png

经典解决方法:容器中存储基类指针

Vehicle* parking_lot[1000];Automobile x;parking_lot[0] = &x;

不足:

内存管理的负担

若容器中的指针在其它地方被释放,会造成大量野指针

经典解决方法的改进:容器中的指针指向原对象的副本

Vehicle* parking_lot[1000];Automobile x;parking_lot[0] =newAutomobile(x);

不足:

动态内存管理的负担

需要知道对象x的静态类型

再次改进:虚复制函数

classVehicle{public:virtualdoubleweight()const=0;virtualvoidstart()=0;virtualVehicle*copy()const=0;virtual~Vehicle() {}};classAircraft:publicVehicle {public:Vehicle*copy()const{returnnewAircraft(*this);    }};classAutomobile:publicVehicle {public:Vehicle*copy()const{returnnewAutomobile(*this);    }};

直接调用copy(),不需要知道x的静态类型

Vehicle* parking_lot[1000];Automobile x;parking_lot[0] = x.copy();

引入代理类

我们引入代理类来避免显式的内存分配。

ab7e6db46fbe2c4915703d05ce418561.png

一个Vehicle代理代表着一个继承自Vehicle的对象,只要该代理关联着该对象,该对象就一定存在。因此,复制该代理就会复制该对象。给代理赋新值也会先删除旧对象,再复制新对象。

classVehicleSurrogate{public:VehicleSurrogate() : vp(0) {}// 注意这个缺省构造,我们需要定义一个“空代理”的概念,类似零指针VehicleSurrogate(constVehicle& v) : vp(v.copy()) {}VehicleSurrogate(constVehicleSurrogate& v) : vp(v.vp ? v.vp->copy() :0) {}VehicleSurrogate&operator=(constVehicleSurrogate& v) {if(this!= &v) {deletevp;vp = (v.vp ? v.vp->copy() :0);             }return*this;       }       ~VehicleSurrogate() {deletevp;       }doubleweight()const{if(vp ==0)throw"vp == 0";             vp->weight();       }voidstart(){if(vp ==0)throw"vp == 0";             vp->start();       }private:       Vehicle* vp;};

需要注意的是,调用vp的成员函数前需要对vp进行判空。

1a3d30f6409a58a285d4a5681ee74cb7.gif

现在我们管理一系列的Vehicle就方便多了:

VehicleSurrogate parking_lot[10];Automobile x;parking_lot[0] = x;

最后一行会调用VehicleSurrogate(const Vehicle& v)完成x从Automobile到VehicleSurrogate的类型转换,而且会创建x的副本。

我们不需要考虑数组中的副本释放问题,VehicleSurrogate的析构函数会帮我们做好。不同类型的对象,放进同一个容器。(下文以数组表示容器)

代理类

问题:

现有不同种类的交通工具类派生层次,如下:

classVehicle{public:virtualdoubleweight()const=0;virtualvoidstart()=0;};classAircraft:publicVehicle {};classAutomobile:publicVehicle {};

我们想对一系列不同各类的Vehicle进行管理:

Vehicle parking_lot[1000];

不足:

抽象类不可实例化

若基类不是抽象类,类型转换会带来问题

经典解决方法:容器中存储基类指针

Vehicle* parking_lot[1000];Automobile x;parking_lot[0] = &x;

不足:

内存管理的负担

若容器中的指针在其它地方被释放,会造成大量野指针

经典解决方法的改进:容器中的指针指向原对象的副本

Vehicle* parking_lot[1000];Automobile x;parking_lot[0] =newAutomobile(x);

不足:

动态内存管理的负担

需要知道对象x的静态类型

再次改进:虚复制函数

classVehicle{public:virtualdoubleweight()const=0;virtualvoidstart()=0;virtualVehicle*copy()const=0;virtual~Vehicle() {}};classAircraft:publicVehicle {public:Vehicle*copy()const{returnnewAircraft(*this);    }};classAutomobile:publicVehicle {public:Vehicle*copy()const{returnnewAutomobile(*this);    }};

直接调用copy(),不需要知道x的静态类型

Vehicle* parking_lot[1000];Automobile x;parking_lot[0] = x.copy();

引入代理类

我们引入代理类来避免显式的内存分配。

一个Vehicle代理代表着一个继承自Vehicle的对象,只要该代理关联着该对象,该对象就一定存在。因此,复制该代理就会复制该对象。给代理赋新值也会先删除旧对象,再复制新对象。

classVehicleSurrogate{public:VehicleSurrogate() : vp(0) {}// 注意这个缺省构造,我们需要定义一个“空代理”的概念,类似零指针VehicleSurrogate(constVehicle& v) : vp(v.copy()) {}VehicleSurrogate(constVehicleSurrogate& v) : vp(v.vp ? v.vp->copy() :0) {}VehicleSurrogate&operator=(constVehicleSurrogate& v) {if(this!= &v) {deletevp;vp = (v.vp ? v.vp->copy() :0);             }return*this;       }       ~VehicleSurrogate() {deletevp;       }doubleweight()const{if(vp ==0)throw"vp == 0";             vp->weight();       }voidstart(){if(vp ==0)throw"vp == 0";             vp->start();       }private:       Vehicle* vp;};

需要注意的是,调用vp的成员函数前需要对vp进行判空。

现在我们管理一系列的Vehicle就方便多了:

2ec23b7cacbdc5b2e13fac45f8293b40.png
VehicleSurrogate parking_lot[10];Automobile x;parking_lot[0] = x;

最后一行会调用VehicleSurrogate(const Vehicle& v)完成x从Automobile到VehicleSurrogate的类型转换,而且会创建x的副本。

我们不需要考虑数组中的副本释放问题,VehicleSurrogate的析构函数会帮我们做好。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值