C++句柄解析
C++句柄类解析
引题:在C++中,对于运行时类型识别问题。在程序中使用引用或者指针在运行时动态识别对象类型。然而使用指针或者引用却增加了用户负担(在继承体系中,没有明确的基类到派生类的转换,必须用户显示转换并将结果对象加入容器中。但是这样的做法结果却是派生对象部分成员是未初始化的)。
对于这一问题,可以将对象指针 保存在容器中来解决。但此时,用户必须明确容器中指针和 对象的同步性(不能只有指针而对象不存在或者收指针不存在,对象存在)。
更好的解决方案就是句柄类了:
C++ 中一个通用的技术是定义包装(cover)类或句柄类。句柄类存储和管 理基类指针。指针所指对象的类型可以变化,它既可以指向基类类型对象又可以 指向派生类型对象。用户通过句柄类访问继承层次的操作。因为句柄类使用指针 执行操作,虚成员的行为将在运行时根据句柄实际绑定的对象的类型而变化。因 此,句柄的用户可以获得动态行为但无须操心指针的管理。
包装了继承层次的句柄有两个重要的设计考虑因素:
- 对任何保存指针的类一样,必须确定对复制控制做些什 么。包装了继承层次的句柄通常表现得像一个智能指针 或者像一个值。
- 句柄类决定句柄接口屏蔽还是不屏蔽继承层次,如果不屏蔽继承层次,用 户必须了解和使用基本层次中的对象。
①指针型句柄:
句柄包装指针,用户可以将该句柄类当作指针使用,却不用去管理指针指向的对象。(句柄类更像是一个中介控制者)
定义方案:
1. 使用类包装指针,包装计数器(每个对象都有各自的这两个成员)
2.使用类包装指针,包装计数器指针(资源和计数器共享)
句柄类除了定义构造,拷贝构造,赋值,还需要定义引用,解引用(使之看起来更像是指针)
对于构造函数:
1个默认构造函数初始化成员为0;
1个构造函数声明指定对象类型的句柄。
那么问题来了,如果用户并不知晓用 继承体系中具体哪个层次对象进行初始化,如何做呢。
解决这个问题的通用方法是定义虚操作进行复制,我们称将 该操作命名为 clone。(克隆):
对于继承层次中的每个类,增加一个虚克隆函数eg:
- class Item_base
- {
- public:
- virtual Item_base* clone() const
- {
- return new Item_base(*this);
- }
- };
有了克隆函数那么 句柄类的定义如下:
- Sales_item::Sales_item(const Item_base &item):
- p(item.clone()), use(new std::size_t())
- { }
对于继承层次中 如果需要逻辑比较函数,一个好的做法是 定义内部比较,比较内部核心成员。
- inline bool
- compare(const Sales_item &lhs, const Sales_item &rhs)
- {
- return lhs->book() < rhs->book();
- }
使用带关联容器的比较器
要有效地工作,关联容器需要对每个操作使用同一比较函数。然而,期望用 户每次记住比较函数是不合理的,尤其是,没有办法检查每个调用使用同一比较 函数。因此,容器记住比较函数是有意义的。通过将比较器存储在容器对象中, 可以保证比较元素的每个操作将一致地进行。
这种做法,实质上就是使用函数指针,函数回调实现真正的比较。
// type of the comparison function used to order the multiset
typedef bool (*Comp)(const Sales_item&, const Sales_item&);
关联容器的每个构造函数使我们能够提供比较函数的名 字。可以这样定义使用 compare 函数的空 multiset:
std::multiset<Sales_item, Comp> items(compare);
multiset 是STL中的联合容器。。在头文件<set>中,具体用法请参看《STL源码剖析》
参考(C++primer)
C++句柄解析的更多相关文章
- (转)WINDOWS内核对象
WINDOWS内核对象 原文地址:http://blog.csdn.net/misterliwei/article/details/976988 支持原创 一.前言 Windows中有很多像进程对象 ...
- 在C++中使用C#编写的类2
在那篇<在C#中使用C++编写的类>中我介绍了如何在C#中使用C++编写的类.可是由于C#在用户界面设计.数据库存储和XML文件读取等方面的优势,有时候也会出现要在C++中使用C#编写的类 ...
- JDK8中JVM对类的初始化探讨
在<深入理解Java虚拟机>(第二版,周志明著)中,作者介绍了JVM必须初始化类(或接口)的五种情况,但是是针对JDK7而言的. 那么,在JDK8中,这几种情况有没有变化呢?(我猜测应该会 ...
- JDK 8 - JVM 对类的初始化探讨
在<深入理解 Java 虚拟机>(第二版,周志明著)中,作者介绍了 JVM 必须初始化类(或接口)的五种情况,但是是针对 JDK 7 而言的. 那么,在 JDK 8 中,这几种情况有没有变 ...
- C#与西门子PLC通讯
1.0 通讯组件概述 通讯组件用于PC与可编程控制器(PLC).智能仪表等进行数据通讯,适用于基于PC高级语言的工业自动化控制系统.组件采用动态链接库文件(*.DLL)的形式,在PC系统的项目工程里 ...
- JVM解毒——类加载子系统
带着问题,尤其是面试问题的学习才是最高效的.加油,奥利给! 点赞+收藏 就学会系列,文章收录在 GitHub JavaEgg ,N线互联网开发必备技能兵器谱 直击面试 看你简历写得熟悉JVM,那你说说 ...
- JVM详解之:类的加载链接和初始化
目录 简介 加载 运行时常量池 类加载器 链接 验证 准备 解析 初始化 总结 简介 有了java class文件之后,为了让class文件转换成为JVM可以真正运行的结构,需要经历加载,链接和初始化 ...
- React-Native知识点相关
React-Native相关 一,为什么要使用React-native? Hybrird的首屏时间太慢,白屏太久,影响用户体验: 原生native开发成本较高: 这里补充一点Webview的性能优化: ...
- JVM之类加载器子系统
类加载器子系统 作用 负责从文件系统或网络系统中加载class文件,class文件在开头有特殊的标记(魔术开头CA FE BA BE) ClassLoader只负责加载class文件,至于能否运行,由 ...
随机推荐
- C#中的一些基础
值类型与引用类型 值类型包括:[基本数据类型,如int,double,char,bool等][枚举类型enum][结构类型struct] 引用类型包括:[类类型,如基类Object,字符串类Strin ...
- tomcat配置内存
windows: Create a new script named as setenv.bat under TOMCAT_HOME/bin folder holding the following ...
- 浅谈AC自动机
写在前面:从10月23日开始写这篇博文,离NOIP2018只有十多天了.坚持不停课的倔强蒟蒻(我)尽量每天挤时间多搞一搞信竞(然而还要准备期中考试).NOIP争取考一个好成绩吧. 一.简介 AC自动机 ...
- 6、LwIP协议规范翻译——缓冲及内存管理
6.缓冲及内存管理 在一个通信系统中,内存缓冲管理系统必须容纳各种大小的缓冲数据,其范围从包含具有数百个字节的数据的全尺寸TCP段到只有几个字节的短ICMP回复包.此外,为了避免拷贝,应该让数据内容缓 ...
- (3.1)mysql备份与恢复之mysqldump
目录: 1.单实例联系 1.1.备份单个数据库联系多种参数使用 [1]mysqldump命令备份演示 [2]查看备份文件 [3]用备份文件还原 1.2.mysqldump 各类参数释义 [1]--de ...
- redis安装及错误排查
安装: 1.cd /usr/redis //redis目录作为安装目录,没有自行创建 2.tar xzf redis-4.0.6.tar.gz 3. cd redis-4.0.6 4.make ...
- Spark实时案例
1.概述 最近有同学问道,除了使用 Storm 充当实时计算的模型外,还有木有其他的方式来实现实时计算的业务.了解到,在使用 Storm 时,需要编写基于编程语言的代码.比如,要实现一个流水指标的统计 ...
- 用 python 生成一个简单的词云图
import jieba from nltk import * from wordcloud import WordCloud import matplotlib.pyplot as plt word ...
- Why Choose MB SD C5 with Engineer Software
MB SD C5 with engineer software performed good and now is released. Unlike the old clone C5 which us ...
- Scala--reduceLeft
reduceLeft神语法 val a = Array(20, 12, 6, 15, 2, 9) 1 2 3 4 5 6 7 8 scala> a.reduceLeft(_ + _) // 数 ...