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

上一回讨论的句柄技术有一个明显的缺点:为了将句柄捆绑到类T的对象上,必须要新定义一个具有类型为T的成员对象的新类。

这个毛病相当麻烦,如果想新设计一个类的句柄类,就需要新定义两个类。


C++之父提到过一种定义句柄类的技术可以弥补这一个缺点,主要思想就是将引用技术从数据中分离出来,把引用计数放到句柄类自己的对象之中。

示例代码如下所示:

#include <iostream>
using namespace std;
//-----------------------------------------
class Point
{
private:
	int xval,yval;
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;}
};
//------------------------------------------------------

class UseCount
{
private:
	int* p;
public:
	UseCount();
	UseCount(const UseCount&);
	UseCount& operator=(const UseCount&);
	~UseCount();
	bool only();
	bool reattach(const UseCount&);
	bool make_only();
};
UseCount::UseCount():p(new int(1)){}
UseCount::UseCount(const UseCount&u):p(u.p){++*p;}
UseCount::~UseCount()
{
	if (--*p==0)
	{
		delete p;
	}
}
bool UseCount::only()
{
	return *p==1;
}
bool UseCount::reattach(const UseCount& u)
{
	++*u.p;
	if (--*p==0)
	{
		delete p;
		p=u.p;
		return true;
	}
	p=u.p;
	return false;
}
bool UseCount::make_only()
{
	if (*p==1)
		return false;
	--*p;
	p=new int(1);
	return true;
}
//-------------------------------------------

class Handle
{
private:
	Point* p;
	UseCount u;
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);
};
Handle::Handle():p(new Point){}
Handle::Handle(int x,int y):p(new Point(x,y)){}
Handle::Handle(const Point&p0):p(new Point(p0)){}
Handle::Handle(const Handle&h):u(h.u),p(h.p){}
Handle::~Handle()
{
	if (u.only())
	{
		delete p;
	}
}
Handle& Handle::operator=(const Handle &h)
{
	if (u.reattach(h.u))
		delete p;
	p=h.p;
	return *this;
	/* //自定义版本不使用reattach辅助方法,自认为更容易理解,但很丑陋
	(*(h.u.p))++;
	if(*(u.p) == 1)
	{
		delete p;
		delete u.p;
	}
	else
		(*(u.p))--;
	u.p = h.u.p;
	p = h.p;	
	return *this;
	*/
}
int Handle::x()const
{
	return p->x();
}
int Handle::y()const
{
	return p->y();
}
Handle& Handle::x(int x0)
{
	if (u.make_only())
		p=new Point(*p);
	p->x(x0);
	return *this;
	/* //自定义版本,不使用辅助方法make_only,自认为更容易理解,但很丑陋
	if(*(u.p) == 1)
		p->x(x0);
	else
	{
		(*(u.p))--;
		u.p = new int(1);
		p = new Point(*p);
		p->x(x0);
	}
	retrun *this;
	*/
}
Handle& Handle::y(int y0)
{
	if (u.make_only())
		p=new Point(*p);
	p->y(y0);
	return *this;
	/* //自定义版本,不使用辅助方法make_only,自认为更容易理解,但很丑陋
	if(*(u.p) == 1)
		p->y(x0);
	else
	{
		(*(u.p))--;
		u.p = new int(1);
		p = new Point(*p);
		p->y(x0);
	}
	retrun *this;
	*/	
}
//---------------------------------------------------

int main()
{
	Handle h(3,4);
	Handle h2 = h;
	h2.x(5); 
	int n = h.x();
	cout<<n<<endl;
	return 0;
}


这个策略的一个重要优势:UseCount类可以在不了解其使用者任何信息的情况下与之合为一体。这样一来,我们就可以把这个类当成句柄实现的一部分,与各种不同的数据结构协同工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值