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++句柄解析的更多相关文章

  1. (转)WINDOWS内核对象

    WINDOWS内核对象 原文地址:http://blog.csdn.net/misterliwei/article/details/976988  支持原创 一.前言 Windows中有很多像进程对象 ...

  2. 在C++中使用C#编写的类2

    在那篇<在C#中使用C++编写的类>中我介绍了如何在C#中使用C++编写的类.可是由于C#在用户界面设计.数据库存储和XML文件读取等方面的优势,有时候也会出现要在C++中使用C#编写的类 ...

  3. JDK8中JVM对类的初始化探讨

    在<深入理解Java虚拟机>(第二版,周志明著)中,作者介绍了JVM必须初始化类(或接口)的五种情况,但是是针对JDK7而言的. 那么,在JDK8中,这几种情况有没有变化呢?(我猜测应该会 ...

  4. JDK 8 - JVM 对类的初始化探讨

    在<深入理解 Java 虚拟机>(第二版,周志明著)中,作者介绍了 JVM 必须初始化类(或接口)的五种情况,但是是针对 JDK 7 而言的. 那么,在 JDK 8 中,这几种情况有没有变 ...

  5. C#与西门子PLC通讯

    1.0  通讯组件概述 通讯组件用于PC与可编程控制器(PLC).智能仪表等进行数据通讯,适用于基于PC高级语言的工业自动化控制系统.组件采用动态链接库文件(*.DLL)的形式,在PC系统的项目工程里 ...

  6. JVM解毒——类加载子系统

    带着问题,尤其是面试问题的学习才是最高效的.加油,奥利给! 点赞+收藏 就学会系列,文章收录在 GitHub JavaEgg ,N线互联网开发必备技能兵器谱 直击面试 看你简历写得熟悉JVM,那你说说 ...

  7. JVM详解之:类的加载链接和初始化

    目录 简介 加载 运行时常量池 类加载器 链接 验证 准备 解析 初始化 总结 简介 有了java class文件之后,为了让class文件转换成为JVM可以真正运行的结构,需要经历加载,链接和初始化 ...

  8. React-Native知识点相关

    React-Native相关 一,为什么要使用React-native? Hybrird的首屏时间太慢,白屏太久,影响用户体验: 原生native开发成本较高: 这里补充一点Webview的性能优化: ...

  9. JVM之类加载器子系统

    类加载器子系统 作用 负责从文件系统或网络系统中加载class文件,class文件在开头有特殊的标记(魔术开头CA FE BA BE) ClassLoader只负责加载class文件,至于能否运行,由 ...

随机推荐

  1. PrimeNG之DataTable

    --数据表显示在表格格式数据. Basic Import import {DataTableModule,SharedModule} from 'primeng/primeng'; source &l ...

  2. 基于Enterprise Architect完成数据库建模

    基于Enterprise Architect完成数据库建模 “工欲善其事必先利其器”,Enterprise Architect是一款非常便利的设计工具,目前我也是刚刚使用没多久,进行过系统设计.UML ...

  3. MongoDB 目录

    MongoDB 介绍 centos7.6 安装与配置 MongoDB yum方式 MongoDB 数据库操作 MongoDB 用户管理 MongoDB 新建数据库和集合 查询集合 MongoDB 增删 ...

  4. django 1.11 目录

    django 信号 django form

  5. python类型错误:'NoneType' object is not subscriptable

    TypeError: 'NoneType' object is not subscriptable --> 原因:变量使用了系统内置的关键字list 解决:重新定义下这个变量

  6. pandas的Panel类型dtype

    panel = pd.Panel(dataframe_dict) 把一个多列类型不相同(里面有int,float)的dataframe字典直接赋值给Panel,从Panel中解析出来的datafram ...

  7. Jenkins Pipeline脚本

    node { echo 'Hello World' } node 在Jenkins环境中分配一个执行器和工作空间. echo 在控制台输出中写入简单的字符串 try { timeout(time: 1 ...

  8. python-17

    # 列表生成式 a = [x*2 for x in range(10)] # 这两个变量必须一致 print(a) #列表 元组的高级赋值办法 b,c = [",6] # python的垃圾 ...

  9. sublime开启vim模式

    sublime自带vim模式Vintage,只是默认是ignore状态,因此如果按Esc键没有进入vim模式,只需要按ctrl+shift+P进入命令模式,键入Enable package,输入Vim ...

  10. Numpy 数据类型和基本操作

    Numpy 数据类型 bool 用一位存储的布尔类型(值为TRUE或FALSE) inti 由所在平台决定其精度的整数(一般为int32或int64) int8 整数,范围为128至127 int1 ...