句柄类作用主要有两个:

  • 支持面向对象编程,实现多态性质;
  • 减少头文件的编译依赖关系,让文件间的编译更加独立。

句柄类存储和管理基类指针,指针既可以指向基类类型对象又可以指向派生类型对象。用户通过句柄类访问继承层次的操作,用户可以获得动态行为,同时能够确保自动正确的销毁动态分配的对象,防止内存泄露。《C++ Primer》15.7节中用购物篮的例子说明了C++不能通过对象支持多态,而必须使用指针或引用。如果multiset保存基类的对象:派生类对象只有基类部分保存下来,而派生类部分被切掉;如果保存派生类的对象,基类对象无法有效转换为派生类对象。

在Effective C++类的实现中条款22说明了为了实现接口和实现的分离,将对象的实现隐藏在指针身后,这样就能减少头文件的编译依赖关系。实现技术:使用引用数(referencecount)。句柄类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。计数器变化的情况:

  • 创建类的新对象时,初始化指针并将引用计数置为1;
  • 对象作为另一对象的副本,拷贝构造函数拷贝指针并增加与之相应的引用计数;
  • 对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;
  • 调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除对象)。

一、指针型句柄

定义一个句柄类,管理继承层次中对象的指针,同时使用引用计数,自动释放相关继承类的对象。

//基类
class A{
public:... //类定义virtual A *clone() const //虚函数,复制基类对象指针{ return new A(*this); }
private:... //类定义
};
//派生类
class B : public  A {
public:... //类定义B *clone() const //重写,复制派生类对象指针{ return new B(*this); }
private:... //类定义
};//句柄类,管理对象指针和引用计数
class C{
public:C() : p(0), use( new int(1)) {}// 用继承中的对象生成句柄类对象C( const A &a ) : p( a.clone()), use( new int(1)) {}//复制构造函数C( const Handle &h ) :p(h.p), use(h.use) { ++*use; } //计数加1~C() { decr_use(); }const A *operator->() const  //返回对象指针{ if(p) return p; }const A &operator*() const //返回对象{ if(p) return *p; }C &operator=( const C &); //赋值
private:A *p; //对象指针int *use; //引用计数
void decr_use()
{if(--*use == 0){ delete p; delete use; }
}
};

赋值操作

C &C::operator=( const C &rhs )
{++&rhs.use; //右操作数计数加1decr_use(); //检查左操作数计数p = rhs.p; //赋值use = rhs.use;return *this;
}

句柄类的使用

A a;
C h1(a); //用一个基类对象生成一个句柄类对象
C h2(h1); //用h1来初始化h2,它们对象指针指向同一个对象 a,计数指针指向同一个值。
B b;
C h3(b); //派生类对象生成一个句柄类对象
multiset<C> mc;
mc.insert(h1);
mc.insert(h2);
mc.insert(h3); //所有对象都能被完整保存
//注意:插入关联容器需要对象有比较函数

二、泛型句柄类

由于(一)中句柄类包含指向继承层次中某类型对象指针和计数式的复制控制,因此可以定义一个句柄类模版,管理指针和进行使用计数。

template <class T> class Handle {
public:// 默认构造函数Handle( T *p = 0 ): ptr(p), use( new int(1) ) { }// 复制构造函数Handle( const Handle& h ): ptr(h.ptr), use(h.use){ ++*use; }//重载操作符 * 和 -> ,const 和 非const版本T& operator*();T* operator->();const T& operator*() const;const T* operator->() const;// 重载操作符 =Handle& operator=( const Handle& );~Handle() { rem_ref(); }
private:T* ptr; // 对象指针int *use; // 引用计数void rem_ref(){if (--*use == 0) { delete ptr; delete use; } }
};

基类A、派生类B和模版类中的其它函数的定义与(一)中,不再重复。

泛型句柄类使用

class C{
public://默认构造函数C() : h() {}// 复制构造函数C( const A &a ) : h(a.clone()) {}//重载操作符 * 和 ->const A &operator*() const { return *h; }const A *operator->() const { return h.operator->(); }
private:Handle<A> h; // 使用句柄类
};

由于这个版本的类C没有指针成员,所以不需要复制控制成员,管理使用计数和相关对象的工作在 Handle 内部完成。

可以将使用模版句柄类定义的类C与原来的类C进行对比:两个类接口没有改变,因此类C的使用与上面相同。

C++句柄类(智能指针)小结相关推荐

  1. 【c++手记】句柄类智能指针

    很多同学学习c++都会看的一本经典教材<Primer> 而在面向对象里面提及到一种概念-智能指针,而往往同学会出现以下的问题 [问题] 智能指针是不是一种指针? stl里面的智能指针是什么 ...

  2. 指针嵌套指针 拷贝_C++智能指针小结

    C++中的智能指针包括auto_ptr, unique_ptr, shared_ptr, weak_ptr. 其中 auto_ptr已被弃用. unique_ptr unique_ptr是大部分情况下 ...

  3. android wp指针使用方法,Android智能指针RefBase、sp、wp解析

    [TOC] 在Android系统中,Native层的代码基本都是C++写的,C++跟Java不一样,C++没有垃圾回收机制,C++代码中难于管理new出来对象的释放,稍有不慎就造成内存泄漏.针对此问题 ...

  4. android 绘指针,Android智能指针

    "Yeah It's on. " 前言 在Android系统中,Native层的代码基本都是C++写的,C++跟Java不一样,C++没有垃圾回收机制,C++代码中难于管理new出 ...

  5. 虚幻C++入门个人笔记(3)——接口、智能指针、动画蓝图、行为树、EQS系统

    接口 接口的词义广泛,用来陈述功能.选项,与其他程序结构进行沟通的方式.接口抽象出了交互结构,提供了两个未知逻辑交互的便捷性.对于编程中,如何更好地设计低耦合程序起到了至关重要的作用.设计者可以在互不 ...

  6. C++语法——详解智能指针的概念、实现原理、缺陷

    目录 一.智能指针的概念 (一).智能指针的历史 (二).智能指针的使用 插曲.auto_ptr ①unique_ptr ②shared_ptr ③weak_ptr 二.智能指针的实现 三.智能指针的 ...

  7. C++智能指针shared_ptr、unique_ptr以及weak_ptr

    目录 shared_ptr类 shared_ptr和unique_ptr都支持的操作 shared_ptr独有的操作 make_shared函数 shared_ptr自动销毁所管理的对象 由普通指针管 ...

  8. UE进阶实例40(STL与Unreal的智能指针)

    STL智能指针 智能指针是C++11新引入的模板内存工具类,在std的命名空间下,早年有接触过cococs2d-x的开发者可能知道类似 于智能指针的功能原理,在有引用的时候,将引用计数器自增,丢失引用 ...

  9. C++智能指针:更简单、更高效的内存管理方法

    C++智能指针:从新手到高手的心理密码C++ Smart Pointers: Psychological Passcodes from Beginner to Expert 智能指针简介 (Intro ...

  10. C++代理类,句柄(智能指针)_C++沉思录笔记

    代理类 首先定义三个类: class Animal{ public:virtual void getName()=0;virtual void clone()=0; };class Cat:publi ...

最新文章

  1. 为什么“15。。。”会导致微信ANR?
  2. 测试晶面间距软件_【干货】高分辨TEM晶面间距的测量与标定丨DM软件
  3. android studio 模拟器中文乱码
  4. Eclipse相关问题总结
  5. python的类和实例化对象
  6. Java jdt 编辑_JDT入门
  7. 哪个内存更快?Heap或ByteBuffer或Direct?
  8. 负载均衡 > 用户指南 > 证书管理 > 证书要求
  9. Retrofit请求数据对错误以及网络异常的处理
  10. IDC商人应不应该给客户提供服务器测试?```
  11. adaptec SCSI卡管理和配置选项
  12. Android SD卡操作
  13. Matlab数字孪生
  14. 快手批量下载-支持作者所有视频无水印带标题
  15. xt5 连接android auto,2021年凯迪拉克XT6将添加无线Apple CarPlay和Android Auto
  16. maven 打包命令
  17. Gym包的安装与使用(新旧版本问题,Atari游戏支持问题)
  18. 携程网创始人季琦:互联网已不再有机会(转)
  19. python把两个图片合成一张图
  20. 全国各地dns服务器列表

热门文章

  1. 综合布线实训室解决方案(转载)
  2. mac软件下载常用经典网站
  3. ST-Link 驱动安装
  4. 数据结构 实验2——表达式求值
  5. Oracle批量导出Hive建表语句
  6. chrome open axure 自动跳转到axure插件
  7. stm32+esp8266+app inventor简单小制作
  8. 微信小程序弹框wx.showToast、wx.showModal样式修改
  9. visio画图——圆柱
  10. c语言printf()输出格式大全(转载)