一、问题

  如何设计一容器能包含彼此不同而又相互关联的类的对象(处于完整的继承层次的类)?因为一般的数组容器都只能包含一种类型的对象。  

  假设有一个表示不同类型的交通工具的类的派生层次:

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++ 沉思录---代理类的更多相关文章

  1. 【C++沉思录】代理类

    1.考虑下面的场景:设计一个容器,包含一组类型不同但相互关联的对象(比如:Animal,Dog,Cat),对象具备多态行为.2.容器一般只能包含一种类型的对象,使用vector<Animal&g ...

  2. c++沉思录 学习笔记 第五章 代理类

    Vehicle 一个车辆的虚基类 class Vehicle {public: virtual double weight()const = 0; virtual void start() = 0; ...

  3. OOD沉思录 --- 面向动作与面向对象 --- 避免泛滥成灾的类

    3.7 从设计中取出不需要的类 只有Get/Set方法的类不算是一个必要的类,Get/Set方法也不算是有意义的行为.这种类降级为属性更加合适. 3.8 去除系统外部的类 如果一个类只调用系统领域的方 ...

  4. 【C++沉思录】句柄1

    1.在[C++沉思录]代理类中,使用了代理类,存在问题: a.代理复制,每次创建一个副本,这个开销有可能很大 b.有些对象不能轻易创建副本,比如文件2.怎么解决这个问题? 使用引用计数句柄,对动态资源 ...

  5. 生活沉思录 via 哲理小故事

    本文转载:http://www.cnblogs.com/willick/p/3174803.html 1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛, ...

  6. 生活沉思录 via 哲理小故事(一)

    1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛,但却是失明的. 原来,托蒂刚出生时,这只眼睛轻度感染,曾用绷带缠了两个星期.这对常人来说几乎没有人任何 ...

  7. vs2013 手动生成webservice代理类wsdl

    第一步: 第二步: 第三步: 至此wsdl代理类生成成功!

  8. Struts2 源码分析——Action代理类的工作

    章节简言 上一章笔者讲到关于如何加载配置文件里面的package元素节点信息.相信读者到这里心里面对struts2在启动的时候加载相关的信息有了一定的了解和认识.而本章将讲到关于struts2启动成功 ...

  9. iOS Class 使用NSProxy和NSObject设计代理类的差异

    经常发现在一些需要使用消息转发而创建代理类时, 不同的程序员都有着不同的使用方法, 有些采用继承于NSObject, 而有一些采用继承自NSProxy. 二者都是Foundation框架中的基类, 并 ...

随机推荐

  1. akka 练手 原来第一次是原封不动的返回传出去的参数

    今天,有介绍akka的文章,就下了个源码的demo练手! 在TimeServer 这个实例中主要就2个文件 server端 static void Main(string[] args) { usin ...

  2. 对java位运算之异或运算的一点记录

    首先,异或运算是,每个位上的数不同为1,相同为0. 其次,对两个数值变量的值进行三次异或运算就等于是交换了两个变量的值. 例如: int a = 4; int b = 10; a = a ^ b; b ...

  3. C#实现AStar寻路算法

    AStar寻路算法是一种在一个静态路网中寻找最短路径的算法,也是在游戏开发中最常用到的寻路算法之一:最近刚好需要用到寻路算法,因此把自己的实现过程记录下来. 先直接上可视化之后的效果图,图中黑色方格代 ...

  4. c#设计模式之观察者模式(Observer Pattern)

    场景出发 一个月高风黑的晚上,突然传来了尖锐的猫叫,宁静被彻底打破,狗开始吠了,大人醒了,婴儿哭了,小偷跑了 这个过程,如果用面向对象语言来描述,简单莫过于下: public class Cat { ...

  5. 开源应用框架BitAdminCore:更新日志20180903

    索引 NET Core应用框架之BitAdminCore框架应用篇系列 框架演示:https://www.bitadmincore.com 框架源码:https://github.com/chenyi ...

  6. php foreach 遍历细节探讨

    foreach 也是正常的语法循环结构,可以有 break 和 continue 等操作 遍历过程中值变量传递默认是值传递 输出结果为: 遍历过程中值变量可以认为设定为引用传递:foreach($数组 ...

  7. docker为什么适合devops?

    欢迎访问网易云社区,了解更多网易技术产品运营经验 进阶版结论:Kubernetes + Docker 是 Dev 和 Ops 融合的一个桥梁.   DevOps 强调的是高效组织团队之间如何通过自动化 ...

  8. GO学习笔记 - 基本数据类型

    官方教程:https://tour.go-zh.org/basics/11 Go 的基本类型有Basic types bool string int int8 int16 int32 int64 ui ...

  9. Visual Studio code安装步骤

    1.官方下载:https://code.visualstudio.com/,本人电脑是window系统  下载之后,双击安装,安装完之后左侧栏那边是英文,如何变为中文: 按快捷键ctrl+shift+ ...

  10. java实际项目中interface和abstract interface 区别

    参考:https://zhidao.baidu.com/question/424485344260391052.html 这2种有什么区别,根据实际项目经验 帮我解答下 谢谢啊~~~~~~~~~问题补 ...