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. Java截图笔记

  2. Longest Valid Parentheses 每每一看到自己的这段没通过的辛酸代码

    Longest Valid Parentheses My Submissions Question Solution  Total Accepted: 47520 Total Submissions: ...

  3. 写在Ruby之前。

    jeiao: 入行程序员也有一年的时间,入门的时候学的Java,在公司写了大半年的Java,也主要是Web方向,使用过struts2 做过项目,后来又用SSH实现了一遍,感觉就那么点意思,因为公司规模 ...

  4. android中include 的使用讲解

    include的作用就是重复使用同一段代码,提高代码的重用性.具体说就是,通过include 在 某布局 a.xml 中引用 B.xml布局文件,这个b.xml可同时被多个布局同时使用,所以达到了同一 ...

  5. .android:allowTaskReparenting 等Activity 的task属性

    转自http://blog.csdn.net/javayinjaibo/article/details/8855678 1.android:allowTaskReparenting 这个属性用来标记一 ...

  6. How to configure windows machine to allow file sharing with dns alias (CNAME)

    Source: http://serverfault.com/questions/23823/how-to-configure-windows-machine-to-allow-file-sharin ...

  7. PHPCMS联动菜单的调用函数get_linkage方法详解

    v9联动菜单调用方法[注意此为内容页调用方法 {get_linkage($areaid,1,' >> ',1)} 显示效果: 湖北省 >> 武汉市 >> 汉阳区 [ ...

  8. Python-同时匹配邮箱和电话号码的正则表达式

    同时匹配邮箱和电话号码的正则表达式要想很完美的匹配,不太简单. 各邮箱提供商的标准都多少有些许差别.如:163:6-18个字符,可使用字母.数字.下划线,需以字母开头. gmail:可以使用字母.数字 ...

  9. How to Read a Book

    主题: 讲述阅读的四种层次,以及每种层次所需要的.截然不同的阅读方法. 主要声明与论点: 带着问题阅读,时刻不忘在书中寻找问题的答案: 高速阅读,以最短的时间了解一本书的全貌,然后决定是否值得再次阅读 ...

  10. HTML5 ——本地存储

    目录 一.HTML4客户端存储 1.1.提交表单发送到服务器的信息 1.2.客户端本地存储概要 二.localStorage 2.1.添加 2.2.取值 2.3.修改 2.4.删除 2.5.跨页面与跨 ...