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文件,至于能否运行,由 ...
随机推荐
- scala-actor线程间通信
import scala.actors.Actor case class Msg(val info: String, act1: MyActor1) class MyActor extends Act ...
- HDFS,MapReduce,Hive,Hbase 等之间的关系
HDFS: HDFS是GFS的一种实现,他的完整名字是分布式文件系统,类似于FAT32,NTFS,是一种文件格式,是底层的. Hive与Hbase的数据一般都存储在HDFS上.Hadoop HDFS为 ...
- caffe中的卷积
https://www.zhihu.com/question/28385679 如上,将三维的操作转换到二维上面去做,然后调用GEMM库进行矩阵间的运算得到最后结果. 两个矩阵相乘,需要中间的那个维度 ...
- Windebug调试
.loadby SOS clr .Symfix .reload !threads !printexception [address]
- javaweb(1)之tomcat使用
安装 1.点击下载. 2.解压到一个目录. 3.进入解压后的 bin 目录,双击该文件夹下的 startup.bat 即可运行. 4.若运行成功,会有一个窗口悬停如下: 访问地址: localhost ...
- Hive中MetaServer与HiveServer2的应用
在hive中有metaServer与hiveServer2两种服务,看了好多文章说这两个的区别,文章内容有对有错,不够全面,故在这里好好总结一下. 首先,下面这个hive构架图,我们一定不陌生,它反应 ...
- return ajax 把ajax链式操作 简易封装
成功就是done,失败就是fail
- string和int的相互转换方法
string转为int string str = "100000"; stringstream ss; ss << str; int i; ss >> i; ...
- 如何通过代码审计挖掘REDos漏洞
写这篇文章的目的一是由于目前网上关于java代码审计的资料实在是太少了,本人作为一个java代码审计的新手,深知学习java代码审计的难受之处,所以将自己学习过程中挖掘的一些漏洞写成博客发出来希望可以 ...
- Gitlab构建分布式版本控制系统
一 安装依赖 1.sudo yum install curl policycoreutils openssh-server openssh-clients 2.sudo systemctl enabl ...