一、问题

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

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

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. Java Web系列:Java Web 项目基础

    1.Java Web 模块结构 JSP文件和AXPX文件类似,路径和URL一一对应,都会被动态编译为单独class.Java Web和ASP.NET的核心是分别是Servlet和IHttpHandle ...

  2. struts2设置index.action为主页(另:web.xml编辑卡死问题解决)

    本来是弄拦截器的问题,结果弄主页的时候,还是发现了问题. 公司网站的项目里面,是用index.action作为主页的,访问WEB-INF里面的html文件.可是我设置的却不成功,追根到底,一个原因,s ...

  3. 解决“找不到请求的 .Net Framework Data Provider。可能没有安装.”错误

    问题: 这几天在装.NET 的开发环境,在装好VS2013和Oracle 11g之后,做了一个测试项目,运行调试没问题 但是涉及到数据库相关操作,如新建数据集.连接数据库等在调试的时候则会出现如下错误 ...

  4. 字体变色详解链接:https://www.cnblogs.com/daofaziran/p/9015284.html

    格式:\033[显示方式;前景色;背景色m + 结尾部分:\033[0m 字体色 | 背景色 | 颜色描述 ------------------------------------------- 30 ...

  5. C# 调用人脸识别 虹软ArcFace2.0实例

    虹软SDK推出了2.0版本,这个版本的所有API都集合在一个动态库里面,再通过引擎库调用,比1.2版本相对轻便了很多. 了解详情戳这里 小西瓜也迫不及待弄了一个新版本的C#实例,基于VS2013开发的 ...

  6. 对象初始化的完整过程(C#)

    1.静态构造函数 在引入本文的主题之前,我们先来铺垫一下吧,看看静态构造函数的概念及用途. C#中允许创建无参数构造函数,该函数仅执行一次.它一般被用来初始化静态字段.CLR不能保证在某个特定时刻执行 ...

  7. sharepoint database 操作

    select *from [dbo].[AllLists] where tp_Title='Pages' and tp_WebId='90511126-E1FE-4E4C-8DDF-74DFC89E8 ...

  8. “全栈2019”Java异常第四章:catch代码块作用域详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  9. 工具IDEA 配置springboot+maven项目

    工具IDEA 配置springboot+maven项目 首先安装IDEA,至于怎么安装就不介绍了.. 第一步 配置maven环境 首先安装maven,先在网上下载一个maven包.在IDEA的sett ...

  10. 将参数传递给ASP.NET Core 2.0中的中间件

    问题 在ASP.NET Core的安装过程中,如何将参数传递给中间件? 解 在一个空的项目中添加一个POCO类来保存中间件的参数, publicclass GreetingOptions { publ ...