1、【C++沉思录】句柄1 存在问题:
句柄为了绑定到Point的对象上,必须定义一个辅助类UPoint,如果要求句柄绑定到Point的子类上,那就存在问题了。
2、有没有更简单的办法呢?
句柄使用Point*直接绑定到Point对象上(包括子类),为了保持多个句柄引用计数的一致性,使用int* 指向引用计数。
3、代码如下:
#include "point.h"
class Handle_2
{
public:
Handle_2():_p(new Point),_u(new int(1)){}

Handle_2(int x,int y):_p(new Point(x,y)),_u(new int(1)){}

Handle_2(const Point& rhs):_p(new Point(rhs)),_u(new int(1)){}

~Handle_2()
{
subRef();
}

Handle_2(const Handle_2& rhs)
{
addRef(rhs);
}

Handle_2& operator=(const Handle_2& rhs)
{
if(this != &rhs)
{
subRef();
addRef(rhs);
}

return * this;
}

int GetX()
{
return _p->GetX();
}

int GetY()
{
return _p->GetY();
}

Handle_2& SetX(int x)
{
if(*_u == 1) // 当前是唯一的引用
{
_p->SetX(x);
}
else
{
--*_u;
_p = new Point(x,_p->GetY());
}
return *this;
}

Handle_2& SetY(int y)
{
if(*_u == 1) // 当前是唯一的引用
{
_p->SetY(y);
}
else
{
--*_u;
_p = new Point(_p->GetX(),y);
}
return *this;
}

private:
void addRef(const Handle_2& rhs) // 复制对象指针和引用计数指针,增加引用
{
_p = rhs._p;
_u = rhs._u;
++*_u;
}

void subRef()// 减少引用,判断是否delete对象和引用计数
{
if(--*_u == 0)
{
delete _p;
delete _u;
}
}

private:
Point* _p;
int* _u;
};
4、这里要手动管理动态内存 int* _u; 同样道理,可以使用栈上对象进行管理,抽象出一个辅助类 UseCount
class UseCount
{
public:
UseCount():_p(new int(1)){}
UseCount(const UseCount& rhs)
{
addRef(rhs);
}

UseCount& operator=(const UseCount& rhs)
{
if(this != &rhs)
{
subRef();
addRef(rhs);
}
return *this;
}

~UseCount()
{
subRef();
}

bool IsOnly()
{
return (*_p == 1);
}

void MakeOnly()
{
if(IsOnly()) // 防止已经是only,用户还调用MakeOnly
{
return;
}
--*_p;
_p = new int(1);
}

private:
void addRef(const UseCount& rhs)
{
_p = rhs._p;
++*_p;
}

void subRef()
{
if(--*_p == 0)
{
delete _p;
}
}

private:
int* _p;
};

#include "point.h"
#include "use_count.h"
class Handle_2
{
public:
Handle_2():_p(new Point){}

Handle_2(int x,int y):_p(new Point(x,y)){}

Handle_2(const Point& rhs):_p(new Point(rhs)){}

~Handle_2()
{
subRef();
}

Handle_2(const Handle_2& rhs)
{
addRef(rhs);
}

Handle_2& operator=(const Handle_2& rhs)
{
if(this != &rhs)
{
subRef();
addRef(rhs);
}

return * this;
}

int GetX()
{
return _p->GetX();
}

int GetY()
{
return _p->GetY();
}

Handle_2& SetX(int x)
{
if(_u.IsOnly()) // 当前是唯一的引用
{
_p->SetX(x);
}
else
{
_u.MakeOnly();
_p = new Point(x,_p->GetY());
}
return *this;
}

Handle_2& SetY(int y)
{
if(_u.IsOnly()) // 当前是唯一的引用
{
_p->SetY(y);
}
else
{
_u.MakeOnly();
_p = new Point(_p->GetX(),y);
}
return *this;
}

private:
void addRef(const Handle_2& rhs)
{
_p = rhs._p;
_u = rhs._u;
}

void subRef()
{
if(_u.IsOnly())
{
delete _p;
}
}

private:
Point* _p;
UseCount _u;
};

【C++沉思录】句柄2的更多相关文章

  1. 【C++沉思录】句柄1

    1.在[C++沉思录]代理类中,使用了代理类,存在问题: a.代理复制,每次创建一个副本,这个开销有可能很大 b.有些对象不能轻易创建副本,比如文件2.怎么解决这个问题? 使用引用计数句柄,对动态资源 ...

  2. 生活沉思录 via 哲理小故事(四)

    1.围墙里的墓碑 第一次世界大战期间,驻守意大利某小镇的年轻军官结识了镇上的牧师.虽然军官信仰信教,而牧师是天主教牧师,但两人一见如故. 军官在一次执行任务中身负重伤,弥留之际嘱托牧师无论如何要把自己 ...

  3. 生活沉思录 via 哲理小故事

    本文转载:http://www.cnblogs.com/willick/p/3174803.html 1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛, ...

  4. 生活沉思录 via 哲理小故事(一)

    1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛,但却是失明的. 原来,托蒂刚出生时,这只眼睛轻度感染,曾用绷带缠了两个星期.这对常人来说几乎没有人任何 ...

  5. Atitit。 沉思录 与it软件开发管理中的总结 读后感

    Atitit. 沉思录 与it软件开发管理中的总结 读后感 1. <沉思录>,古罗马唯一一位哲学家皇帝马可·奥勒留所著 2 2. 沉思录与it软件开发管理中的总结 2 2.1. 要有自己的 ...

  6. c++沉思录 学习笔记 第六章 句柄(引用计数指针雏形?)

    一个简单的point坐标类 class Point {public: Point():xval(0),yval(0){} Point(int x,int y):xval(x),yval(y){} in ...

  7. c++学习书籍推荐《C++沉思录》下载

    百度云及其他网盘下载地址:点我 编辑推荐 经典C++图书,应广大读者的强烈要求再版 目录 第0章 序幕第一篇 动机第1章 为什么我用C++第2章 为什么用C++工作第3章 生活在现实世界中 第二篇 类 ...

  8. C++模板沉思录(上)

    花下猫语: 在我们读者群里,最近出现了比较多关于 C++ 的讨论,还兴起了一股学习 C++ 的风气.樱雨楼小姐姐对 C++ 的模板深有研究,系统地梳理成了一篇近 4 万字的文章!本文是上篇,分享给大家 ...

  9. C++模板沉思录

    0 论抽象--前言 故事要从一个看起来非常简单的功能开始: 请计算两个数的和. 如果你对Python很熟悉,你一定会觉得:"哇!这太简单了!",然后写出以下代码: def Plus ...

随机推荐

  1. 2004FBI树

    题目描述 Description 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串. FBI树是一种二叉树[1],它的结点类型 ...

  2. Lucene.Net+盘古分词器(详细介绍)(转)

    出处:http://www.cnblogs.com/magicchaiy/archive/2013/06/07/LuceneNet%E7%9B%98%E5%8F%A4%E5%88%86%E8%AF%8 ...

  3. 【原】java环境变量配置&& jdk配置 && 各配置的意义

    本配置需要新建JAVA_HOME和classpath两个: JAVA_HOME 指明JDK安装路径.(在安装好java之后就该配置) classpath 为java加载类(class or lib)路 ...

  4. spring:bean的定义

    一个完整的Bean的配置文件: <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE beans ...

  5. CobarClient源码分析(1)

    CobarClient是阿里巴巴公司开发一个的开源的.基于iBatis和Spring的分布式数据库访问层.为了支持iBatis,Spring框架提供了一个SqlMapClientTemplate,通过 ...

  6. 基于OpenCv的人脸检测、识别系统学习制作笔记之二

    在网上找到了一个博客,里面有大量内容适合初学者接触和了解人脸检测的博文,正好符合我目前的学习方面,故将链接放上来,后续将分类原博客的博文并加上学习笔记. 传送门: http://blog.sina.c ...

  7. 如何卸除SDL TRADOS中的自开发插件

    去年学着用SDL的例子编译了一个名为SimpleText的插件,每次打开TRADOS 2014时都要提示三次加载插件,很是烦人.但我想卸掉时,却无从下手,不知道怎么办.这个问题纠缠了我很久,今晨心性比 ...

  8. halcon摄像机标定

    摄像机标定程序: 注意:E:/calibration_image :为标定图像文件路径       'E:/calibration_description/caltab_123mm.descr:为标定 ...

  9. 针对httptest4net构建elasticsearch集群压力测试用例

    httptest4net是可以自定义HTTP压力测试的工具,用户可以根据自己的情况编写测试用例加载到httptest4net中并运行测试.由于最近需要对elasticsearch搜索集群进行一个不同情 ...

  10. 【转】The difference between categorical(Nominal ), ordinal and interval variables

    What is the difference between categorical, ordinal and interval variables? In talking about variabl ...