C++沉思录读书笔记(二)句柄类.上

原创 2004年07月06日 15:24:00

C++沉思录读书笔记(二)句柄类.上


延续 “C++沉思录读书笔记(一)代理类”
********
问题
********
创建代理将会复制所需要的对象,对某些类来说,复制的代价太大或者包含不能轻易被复制的资源。
如何在保持代理的多态行为的同时,避免复制对象的代价

class Point { //一个简单的类,没有指针成员的函数常常无需重写赋值操作符和复制构造函数
public:
 Point(): xval(0), yval(0) { }
 Point(int x, int y): xval(x), yval(y) { }
 int x() const { return xval; }
 int y() const { return yval; }
 Point& x(int xv) { xval = xv; return *this; }
 Point& y(int yv) { yval = yv; return *this; }
private:
 int xval, yval;
};

********
解决方案
********
@Handle类的轮廓
定义一个适当的Handle类,将Handle类绑定到它们所控制的对象上
要求:
1. Handle类应该创建和销毁对象
  创建自己的Point对象并把它赋给一个handle
  把创建Point的参数传给Handle
2. 通过Handle类访问Point对象
  重载Handle类的operator->操作符,暴露内部的Point对象(本文未采用这种方式)
  明确选择让Handle类支持那些Point操作

class Handle {
public:
 Handle();
 Handle(int, int);
 Handle(const Point&);
 Handle(const Handle&);
 Handle& operator=(const Handle&);
 ~Handle();
 int x() const;
 Handle& x(int);
 int y() const;
 Handle& y(int);
private:
 //...
};

@引用计数
因为允许多个句柄绑定到单个对象上,所以要使用引用计数确定多少个句柄绑定到同一个对象上,以便确定何时删除对象
引用计数不能是句柄的一部分,否则每个句柄必须知道跟它一起被绑定到同一个对象的其他所有句柄的位置(更不能使用static成员)
引用计数不能是对象的一部分,要求不重写已存在的Point对象

class UPoint { //用来存储引用计数和Point对象
private: //纯粹为了实现而设计,所有成员私有
 friend class Handle;
 Point p;
 int u;

 UPoint(): u(1) { } //UPoint对象总是随Handle类产生,因此缺省引用计数为1
 UPoint(int x, int y): p(x, y), u(1) { }
 UPoint(const Point& p0): p(p0), u(1) { }
};

class Handle {
public:
 Handle();
 Handle(int, int);
 Handle(const Point&);
 Handle(const Handle&);
 Handle& operator=(const Handle&);
 ~Handle();
 int x() const;
 Handle& x(int);
 int y() const;
 Handle& y(int);
private:
 UPoint* up; //新添加
};

@Handle类的实现
//构造函数
Handle::Handle(): up(new UPoint) { }
Handle::Handle(int x, int y): up(new UPoint(x, y)) { }
Handle::Handle(const Point& p): up(new UPoint(p)) { }

//析构函数
Handle::~Handle()
{
 if (up->u == 0)
  delete up;
}

//复制构造函数仅仅增加引用计数
Handle::Handle(const Handle& h): up(h.up) { ++up->u; }

//赋值操作符可能造成原左侧对象计数器为0
//先调用++可以保证左右两侧句柄引用同一个UPoint对象时也能工作
Handle& Handle::operator=(const Handle& h)
{
 ++h.up->u;
 if (--up->u == 0)
  delete up;
 return *this;
}

//简单的读函数
int Handle::x() const { return up->p.x(); }
int Handle::y() const { return up->p.y(); }

//复杂的写函数
/*
 句柄类在用户面前的行为
 Handle h(3,4) //原对象
 Handle h2 = h; //复制
 h2.x(5); //修改复制对象
 int n = h.x(); // 3 or 5?
*/

//指针语义:复制句柄类后,复制对象和原对象使用同一个UPoint对象

Handle& Handle::x(int x0)
{
 up->p.x(x0);
 return *this;
}

Handle& Handle::y(int y0)
{
 up->p.y(y0);
 return *this;
}

//值语义:复制句柄类后,复制对象和原对象不使用同一个UPoint对象
//在绝对必要的时候才进行对象复制,称为写时复制(copy on write),写时复制只是针对可变对象的一种优化技术

Handle& Handle::x(int x0)
{
 if (up->u != 1) {
  --up->u;
  up = new UPoint(up->p);
 }
 up->p.x(x0);
 return *this;
}

Handle& Handle::y(int y0)
{
 if (up->u != 1) {
  --up->u;
  up = new UPoint(up->p);
 }
 up->p.y(y0);
 return *this;
}

@图示
+--------+       +--------+       +--------+
| Handle |------>| UPoint |<>---->| Point  |
+--------+       +--------+       +--------+

【java】《java编程思想》 读书笔记

之前主要用的C++的比较多,之前花了快2个月的实际认真系统全面的学习了以下java的基础语法,《java编程思想》这本书翻译水平确实不是很好,很多话读着会比较拗口。推荐读之前,先去网上搜索 “java...
  • a2888409
  • a2888409
  • 2015年10月15日 10:07
  • 1923

《C++沉思录》——类设计核查表、代理类、句柄类

《C++沉思录》——类设计核查表、代理类、句柄类
  • songshiMVP1
  • songshiMVP1
  • 2016年06月04日 14:28
  • 2579

《C++沉思录》读书笔记之代理类

#include #include int main() { int i; for( i=0;i
  • KangRoger
  • KangRoger
  • 2014年06月11日 21:00
  • 1114

C++沉思录读书笔记(7章)-句柄:第二部分

上一回讨论的句柄技术有一个明显的缺点:为了将句柄捆绑到类T的对象上,必须要新定义一个具有类型为T的成员对象的新类。 这个毛病相当麻烦,如果想新设计一个类的句柄类,就需要新定义两个类。 ...
  • yucan1001
  • yucan1001
  • 2011年10月30日 22:12
  • 668

C++沉思录读书笔记(7章)-句柄:第二部分

原文:http://blog.csdn.net/yucan1001/article/details/6919704 上一回讨论的句柄技术有一个明显的缺点:为了将句柄捆绑到类T的对象上,必须要...
  • keke_zkt
  • keke_zkt
  • 2013年04月12日 22:06
  • 583

C++沉思录读书笔记(6章)-句柄:第一部分

创建代理会复制所代理的对象,如何避免这些复制呢?        可以通过句柄(handle)类来实现。句柄类和智能指针有点类似,通过重载句柄类的*和->操作符,可将句柄类改造称为智能指针。    ...
  • yucan1001
  • yucan1001
  • 2011年10月26日 21:37
  • 694

C++沉思录读书笔记(13、14章)-简单容器类的改进

上一回设计的容器类,用户能够轻易的获得指向Vector内部的指针,这种关系暴露了类内部的实现机制,下面加以改进 代码如下: #include using namespace std; t...
  • yucan1001
  • yucan1001
  • 2011年11月07日 11:41
  • 1140

C++沉思录读书笔记(12章)-一个简单容器类的实现

这是一个很简单的容器类,有如下基本功能: 1.不允许对容器赋值,不能使用复制构造函数 2.能使用opertor[]来存取元素,从而与数组类似 3.容器大小定长,能在执行期间才规定容器的长度 4...
  • yucan1001
  • yucan1001
  • 2011年11月07日 10:41
  • 1108

C++沉思录读书笔记(27章)- 设计自己跟踪自己的类

这篇文章的目的是设计提供有关函数执行和类操作调试信息的类 1.一个简单函数跟踪类的设计 class Trace //跟踪类 { public: Trace(const char*...
  • yucan1001
  • yucan1001
  • 2011年11月10日 17:25
  • 821

C++沉思录读书笔记 12-设计容器类

容器是一种保存值的集合的数据结构。C有两种内建的容器:数组和结构体。C++可以提供更多的容器(但是没有)。C++提供给用户写自己的容器的方法。   1. 包含什么 容器包含放在其中的对象的副本,...
  • leechengqian
  • leechengqian
  • 2014年04月01日 11:10
  • 771
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++沉思录读书笔记(二)句柄类.上
举报原因:
原因补充:

(最多只允许输入30个字)