句柄类存在的意义是为了弥补将派生类对象赋给基类对象时发生的切片效应。比如以下的程序:

multimap<Base> basket;
Base base;
Derived derive;
basket.insert(base); //ok,add copy of base;
basket.insert(derive); //ok,but derive sliced down to its base part.

也就是说在把派生类的对象赋值给基类的时候,会发生切片效益,派生类的非基类部分会被切掉,那么就失去了本身的意义。为了解决问题我们能够

使用基于基类的指针或者引用,可是设计到指针问题的话就涉及到资源不使用后的释放问题。这就引出了句柄类,它类似智能指针,能够在我们复制资源

的时候不用去操心内存泄露的问题。整个程序的设计例如以下所看到的:

//Base.h
#pragma once
class Base
{
public:
Base(void);
virtual ~Base(void);
virtual Base* clone() const;
virtual void fine() const;
private:
int mb;
};
//Base.cpp
#include "Base.h"
#include <iostream>
using namespace std; Base::Base(void):mb(12)
{
} Base::~Base(void)
{
} Base* Base::clone() const
{
return new Base(*this);
} void Base::fine() const
{
cout<<"Base fine function"<<endl;
}
//Derive.h
#pragma once
#include "base.h"
class Derive :
public Base
{
public:
Derive(void);
virtual ~Derive(void);
virtual Derive* clone() const;
virtual void fine() const;
private:
int md;
};
//Derive.cpp
#include "Derive.h"
#include <iostream>
using namespace std; Derive::Derive(void):Base(),md(13)
{
} Derive::~Derive(void)
{ } Derive* Derive::clone() const
{
return new Derive(*this);
} void Derive::fine() const
{
cout<<"Derive fine function"<<endl;
}
//Handles.h
#pragma once
#include "Base.h"
#include <iostream>
class Handles
{
public:
Handles(void);
Handles(const Base&);
Handles(const Handles& h);
~Handles(void); const Base* operator->()const;
const Base& operator*()const;
Handles& operator=(const Handles&); private:
Base* p;
std::size_t* use;
void dec_use()
{
if(--*use == 0)
{
delete p;
delete use;
std::cout<<"delete resource"<<std::endl;
}
} };
//Handle.cpp
#include "Handles.h" Handles::Handles(void):p(NULL),use(new size_t(1))
{
} Handles::Handles(const Handles& h):p(h.p),use(h.use)
{
++*use;
} Handles::Handles(const Base& item):p(item.clone()),use(new std::size_t(1))
{
}
const Base& Handles::operator*()const
{
if(p)
return *p;
else
throw std::logic_error("unbounded Handles");
} const Base* Handles::operator->()const
{
if(p)
return p;
else
throw std::logic_error("unbounded Handles");
} Handles& Handles::operator=(const Handles& h)
{
++*h.use;
dec_use();
p = h.p;
use = h.use;
return *this;
} Handles::~Handles()
{
dec_use();
}
//main.cpp
#include <iostream>
#include "Handles.h"
#include "Derive.h"
#include <vector>
using namespace std;
void main()
{
vector<Handles> mb;
Base b;
Derive d;
mb.push_back(Handles(b));
mb.push_back(Handles(d));
mb[0]->fine();
mb[1]->fine();
system("pause");
}

C++ 句柄类的原理以及设计的更多相关文章

  1. C++中的句柄类

    初次在<C++ Primer>看到句柄,不是特别理解.在搜索相关资料后,终于有了点头绪. 首先明白句柄要解决什么问题.参考文章<C++ 沉思录>阅读笔记——代理类 场景: 我们 ...

  2. c++ 容器、继承层次、句柄类

    一.容器与继承 在容器中保存有继承关系的对象,如果定义成保存基类对象,则派生类将被切割,如果定义成保存派生类对象,则保存基类对象又成问题(基类对象将被强制转换成派生类对象,而派生类中定义的成员未被初始 ...

  3. C++ 句柄类

    一.容器与继承 在容器中保存有继承关系的对象时,如果定义成保存基类对象,则派生类将被切割,如果定义成保存派生类对象,则保存基类对象又成问题(基类对象将被强制转换成派生类对象,而派生类中定义的成员未被初 ...

  4. [三]java8 函数式编程Stream 概念深入理解 Stream 运行原理 Stream设计思路

    Stream的概念定义   官方文档是永远的圣经~     表格内容来自https://docs.oracle.com/javase/8/docs/api/   Package java.util.s ...

  5. 2017-2018-1 20179205《Linux内核原理与设计》第六周作业

    <Linux内核原理与设计> 视频学习及操作 给MenuOS增加time和time-asm命令的方法: 1.更新menu代码到最新版 rm menu -rf //强制删除menu, rm ...

  6. atitit.  web组件化原理与设计

    atitit.  web组件化原理与设计 1. Web Components提供了一种组件化的推荐方式,具体来说,就是:1 2. 组件化的本质目的并不一定是要为了可复用,而是提升可维护性. 不具有复用 ...

  7. Atitit.ati dwr的原理and设计 attilax 总结 java php 版本

    Atitit.ati dwr的原理and设计 attilax 总结 java php 版本 1. dwr的优点相对于ajax来说..1 2. DWR工作原理1 3. Dwr的架构2 4. 自定义dwr ...

  8. C++的句柄类

    上一篇文件介绍了关于C++代理类的使用场景和实现方法,但是代理类存在一定的缺陷,就是每个代理类会创建一个新的对象,无法避免一些不必要的内存拷贝,本篇文章引入句柄类,在保持代理类多态性的同时,还可以避免 ...

  9. Atitit.ati&#160;dwr的原理and设计&#160;attilax&#160;总结&#160;java&#160;php&#160;版本号

    Atitit.ati dwr的原理and设计 attilax 总结 java php 版本号 1. dwr的长处相对于ajax来说.. 1 2. DWR工作原理 1 3. Dwr的架构 2 4. 自己 ...

随机推荐

  1. mysql索引的操作

    一.创建和查看普通索引 这是最基本的索引类型,而且它没有唯一性之类的限制 1.创建表时创建普通索引 CREATE TABLE table_name( 属性名 数据类型, ... 属性名 数据类型, I ...

  2. [转]Android定时刷新UI界面----Handler

    本文转自:http://blog.csdn.net/macong01/article/details/7479266 本想做一个软件可以对UI界面进行定时更新,找了一些资料,先贴一个简单的定时更新界面 ...

  3. asp.net mvc 最简单身份验证 [Authorize]通过的标准

    [Authorize] public ContentResult Index2() { return Content("验证通过了"); } 经常能够看到某个Controler下的 ...

  4. MVC系列学习(四)-初识Asp.NetMVC框架

    注:本文章从伯乐那盗了两张图,和一些文字: 1.MVC设计模式 与 Asp.Net Mvc框架 a.MVC设计模式 MVC设计模式 是一种 软件设计模式,将业务逻辑 与 界面显示 分离,并通过某种方式 ...

  5. python读取单个文件操作

    python读取单个文件,参考<笨方法学python>的第15节. 运行方式是采用:python python文件名 要读取的文件名 代码中 script, filename = argv ...

  6. 查看APK包名签名等信息

    有些游戏第三方比如分享需要配置游戏包名和签名,不同渠道包名签名又不同,所以时常需要查看不同apk包等签名信息,之前是使用等微博开放平台的手机客户端查看apk签名,前提是知道包名,网上找了下查看签名和包 ...

  7. eclipse中代码整体左右移动的方法

    1.向左:将要移动的代码选中,然后按TAB键2.向右:将要移动的代码选中,然后按shift+tab键 kettas:  2009-8-21

  8. Android List,Set,Map集合安全 集合区别 并发集合类性能分析

    对于Android开发者来说深入了解Java的集合类很有必要主要是从Collection和Map接口衍生出来的,目前主要提供了List.Set和 Map这三大类的集合 Collection接口主要有两 ...

  9. Jenkins+Ant+Jmeter自动化集成测试实例

    通过学习Jmeter自动化测试,接触到了Ant命令和其构建文件build.xml文件的编写,与此同时,通过将测试项目集成在jenkins上,进一步学习了jenkins的一些环境配置知识.以下是自己的初 ...

  10. jquery制作动态添加表单行与删除表单行

    <script type="text/javascript" src="js/jquery1.7.js"></script> <s ...