【C++沉思录】代理类
1、考虑下面的场景:设计一个容器,包含一组类型不同但相互关联的对象(比如:Animal,Dog,Cat),对象具备多态行为。
2、容器一般只能包含一种类型的对象,使用vector<Animal> 会造成对象切割,不具备多态行为。
3、经典的解决办法是:vector<Animal*>, 但是这会增加内存管理的负担。考虑下面的情况:
Dog d;
vec[i] = &d; // 局部对象d销毁, vec[i] 指向垃圾
vec[i] = vec[j]; // 指向同一个对象, 在vec析构之前,需要手动遍历vec,进行delete,两个delete同一个对象,行为未定义。
4、怎么解决上面的问题,每次都创建一个新的对象。如下:
Dog d;
vec[i] = new Dog(d);
vec[i] = new Animal(vec[j]); // 这里存在问题,由于vec[j] 类型未知,只能使用Animal,但是这造成对象切割。
5、处理编译时类型未知的对象,使用虚方法。Animal 增加一个纯虚方法clone,纯虚方法导致Animal成为一个抽象类,
不能实例化,同时要求子类必须重写clone方法。注:Animal 可以提供纯虚方法clone的实现。
6、Animal* pa = new Dog; delete pa; 为了能够调用Dog的析构方法,定义Animal的析构方法是虚方法。注:多态行为要满足两个条件:
方法是虚方法;表面类型和真实类型不一致。
7、有没有更好的办法呢?
使用代理类,对Animal* 管理。也就是栈上对象管理动态资源,利用C++的一个特性,栈上对象离开作用域,必定会调用析构方法,
在析构方法中释放资源。
8、代码如下:
AnimalProxy::AnimalProxy():_pa(NULL)
{
}
AnimalProxy::~AnimalProxy()
{
delete _pa;
}
// 注意:类中可以访问自己的private成员,也可以访问rhs的private成员
AnimalProxy::AnimalProxy(const AnimalProxy& rhs)
{
_pa = (rhs._pa != NULL ? rhs._pa->Clone():NULL);
}
AnimalProxy& AnimalProxy::operator=(const AnimalProxy& rhs)
{
if(this != &rhs) // 等同测试
{
delete _pa; // delete NULL 也没有问题
_pa = (rhs._pa != NULL ? rhs._pa->Clone():NULL); // 指针为NULL判断
}
return *this; // 返回引用
}
AnimalProxy::AnimalProxy(const Animal& animal):_pa(animal.Clone())
{
}
【C++沉思录】代理类的更多相关文章
- c++ 沉思录---代理类
一.问题 如何设计一容器能包含彼此不同而又相互关联的类的对象(处于完整的继承层次的类)?因为一般的数组容器都只能包含一种类型的对象. 假设有一个表示不同类型的交通工具的类的派生层次: class Ve ...
- 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框架中的基类, 并 ...
随机推荐
- (Python)list的内建函数 filter(), map(), 和 reduce()
这一节,我们将主要学习用于list的三个内建函数: filter(), map(), 和 reduce(). 1.filter(function, sequence) 逐个从sequence中取一个 ...
- 2227 邮票--FUoj(链接表+树的直径)
http://acm.fzu.edu.cn/problem.php?pid=2227 我感觉这道题可以随意搞 题目大意: 给你的一个图就是一条链,但是不知道起始点和结束点,而且每个点只会访问一次. 因 ...
- js-特效部分学习-offsetParent、scrollHeight 、动画函数的封装
1. offsetParent 获取的最近的定位的父元素 offsetLeft/offsetTop 是相对于offsetParent的距离 offsetHeight/offsetWidth 获 ...
- load data ERROR 1197 (HY000)错误
有一份csv格式的文件,大小在14G左右.max_binlog_cache_size=4G. 登录mysql实例,选择对应的表通过load data往指定表里导数.大概20分钟左右,报以下错误: ER ...
- How to Call SharePoint 2013 API Service to Query The Lists
How to Call SharePoint 2013 API In SharePoint 2013, we can query the list by it owner service, then ...
- linux SMP启动
SMP简介 1,硬件上,CPU没有主次之分 2,软件上,每个CPU平等动态地从进程就绪队列中调度进程加以执行,中断请求也是等概率动态的分布给某个CPU SMP启动 1,SMP结构中的CPU都是平等的, ...
- JQuery学习(选择器-基本-*)
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...
- UML建模语言入门 -- 用例视图详解 用例视图建模实战
. 作者 :万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . 一. 用例视图概述 用例视图表述哪些 ...
- 在Github上注册账户
首先打开网址:https://github.com/ 进行注册 注册完成后进入邮箱验证 在右上角创建一个简单的项目仓库 创建完成
- Android相关sdk使用
SimpleDateFormat使用详解 Android_AlertDialog 两分钟彻底让你明白Android Activity生命周期(图文)! Android布局控件之LinearLayo ...