c++ 沉思录---代理类
一、问题
如何设计一容器能包含彼此不同而又相互关联的类的对象(处于完整的继承层次的类)?因为一般的数组容器都只能包含一种类型的对象。
假设有一个表示不同类型的交通工具的类的派生层次:
class Vehicle
{
public:
virtual double weight () const = ;
virtual void start() = ;
//.....
}; class RoadVehicle : public Vehicle
{
public:
/* data */
}; class AutoVehivle : public Vehicle
{
public:
/* data */
}; class Aircraft : public Vehicle
{
public:
/* data */
};
现在我们需要一个容器,这里使用数组表示,能够包含所有上述类的对象,Vehicle parkint_lot[100]; 这样肯定不对
错误原因:1. Vehicle 是个抽象基类(含有纯虚函数),不能实例化对象
2. 假设Vehicle能够实例化也不对,Parking_lot[num_vehicles++] = 派生类对象,这样的操作,会将派生类对象转化为一个Vehicle类的对象,会丢失所有Vehicle类中没有的成员。最后的结果是Parking_lot是Vehicle的集合。
二、解决方案1(传统的解决方法)
通过在数组中存储基类的指针,因为基类的指针转换为派生类的指针是容易且安全的。
Vehicle* Parking_lot[100];
然后输入类似:
Automonbile x =
1: Parking_lot[num_vehicles++] = &x;
存在问题:如果x是局部变量,一旦变量x销毁了,Parking_lot 就不知道指向什么东西了。
2: Parking_lot[num_vehicles++] = new Automobile(x);
存在问题:为了解决1中问题,改用存储对象副本的指针。这种方法会带来一定的内存管理负担,其实我觉得还行,没那么严重,在需求没那么严格的情况下这种方法还是可以使用的。
但是,这种只有当我们确定知道要放入parking_lot对象的静态类型后,才启作用!!!
注意:用基类的指针或引用引用一个派生类对象时,由于派生类对象也是基类的对象,所以这样也是安全的但是只能引用基类中所拥有的成员,不能引用在派生类中定义的成员,否则编译器会报错。
三、解决方案2(代理类)
代理类:定义一个行为和Vehicle对象相似,而又潜在的表示为所有继承自Vehicle类的对象的东西,我们把这种类的对象称之为代理。
在Vehicle类中添加虚复制函数
virtual Vehicle* copy() const = 0;
派生类中实现:
Vehicle* 派生类名称::copy() const{
return new 派生类名称(*this);
}
class VehicleSurrogate
{
public:
VehicleSurrogate();
~VehicleSurrogate();
VehicleSurrogate(const Vehicle& v){
vp(v.copy());
} VehicleSurrogate(const VehicleSurrogate&);
VehicleSurrogate& operator = (const VehicleSurrogate&);
private:
Vehicle* vp;
};
代理类的成员变量为Vehivle 类型的指针,参数为const Vehicle& 类型的构造函数,可以为任意继承自Vehicle的类的对象创建代理。
使用方法:
VehicleSurrogate paking_lot[100];
Automobile x;
Paking_lot[num_vehicles++] = x; 等价于 paking_lot[num_vehicles++] = VehicleSurrogate(x);
c++ 沉思录---代理类的更多相关文章
- 【C++沉思录】代理类
1.考虑下面的场景:设计一个容器,包含一组类型不同但相互关联的对象(比如:Animal,Dog,Cat),对象具备多态行为.2.容器一般只能包含一种类型的对象,使用vector<Animal&g ...
- c++沉思录 学习笔记 第五章 代理类
Vehicle 一个车辆的虚基类 class Vehicle {public: virtual double weight()const = 0; virtual void start() = 0; ...
- OOD沉思录 --- 面向动作与面向对象 --- 避免泛滥成灾的类
3.7 从设计中取出不需要的类 只有Get/Set方法的类不算是一个必要的类,Get/Set方法也不算是有意义的行为.这种类降级为属性更加合适. 3.8 去除系统外部的类 如果一个类只调用系统领域的方 ...
- 【C++沉思录】句柄1
1.在[C++沉思录]代理类中,使用了代理类,存在问题: a.代理复制,每次创建一个副本,这个开销有可能很大 b.有些对象不能轻易创建副本,比如文件2.怎么解决这个问题? 使用引用计数句柄,对动态资源 ...
- 生活沉思录 via 哲理小故事
本文转载:http://www.cnblogs.com/willick/p/3174803.html 1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛, ...
- 生活沉思录 via 哲理小故事(一)
1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛,但却是失明的. 原来,托蒂刚出生时,这只眼睛轻度感染,曾用绷带缠了两个星期.这对常人来说几乎没有人任何 ...
- vs2013 手动生成webservice代理类wsdl
第一步: 第二步: 第三步: 至此wsdl代理类生成成功!
- Struts2 源码分析——Action代理类的工作
章节简言 上一章笔者讲到关于如何加载配置文件里面的package元素节点信息.相信读者到这里心里面对struts2在启动的时候加载相关的信息有了一定的了解和认识.而本章将讲到关于struts2启动成功 ...
- iOS Class 使用NSProxy和NSObject设计代理类的差异
经常发现在一些需要使用消息转发而创建代理类时, 不同的程序员都有着不同的使用方法, 有些采用继承于NSObject, 而有一些采用继承自NSProxy. 二者都是Foundation框架中的基类, 并 ...
随机推荐
- task4: 结对编程-词频统计[修改版]
问题描述: 读取一个文件,统计其中单词出现次数,并按从高到低的顺序显示,相同顺序的字典序排列. 思路: 基于上次的程序用正则提取出文本里的单词,然后利用字典计数(先get,为null则置1,不为nul ...
- MSP430 G2553 低功耗模式LPMx
MSP430除了正常运行时的active模式外,还支持五种低功耗模式(Low-power mode),分别为LPM0.LPM1.LPM2.LPM3.LPM4,由状态寄存器中的CPUOFF.OSCOFF ...
- zookeeper的主要应用
master选举 数据发布和订阅 负载均衡
- (zxing.net)二维码Data Matrix的简介、实现与解码
一.简介 Data Matrix 二维条码原名Datacode,由美国国际资料公司(International Data Matrix, 简称ID Matrix)于1989年发明.Data-Matri ...
- SQLServer 语句相关
--查询两行张表不同的数据 --相同数据 select tel_no from a intersect select tel_no from b --不同数据 select tel_no from ...
- Android intent 传值不更新的原因和解决办法
当 Activity 的启动模式是 singleTask 或者 singleInstance 的时候.如果使用了 intent 传值,则可能出现 intent 的值无法更新的问题.也就是说每次 int ...
- 点击input消除默认背景颜色:focus
1.在谷歌浏览器会出现默认点击input框黄色背景,如何去除? //消除google浏览器黄色框 input:-webkit-autofill, input:-webkit-autofill:hove ...
- gulp 搭建个人工作流:文件注入、热启动、跨域
个人比价推崇前后端分离的开发方式,大家伙各司其职,只需通过 API 进行交流,不仅避免了沟通上的成本,更提升了开发效率.而在前端开发工作中,许多需求和问题是相似的,所以我们的开发模式往往是雷同的,是否 ...
- Azure Powershell部署使用平台映像的托管Windows VM及相关问题说明
1.脚本背景信息: a.使用平台镜像(Windows Server 2016 zh-cn)部署高性能托管磁盘虚拟机 b.虚拟机默认不开启Boot诊断 c.添加三块已经创建好的数据磁盘 d.添加已创建好 ...
- php 内存分配新
https://yq.aliyun.com/articles/38307 https://yq.aliyun.com/ziliao/132720 http://blog.liyiwei.cn/%E3% ...