句柄类(二)
在我的前一篇博文里,我们讨论了有关句柄类的实现,这个句柄类有一个明显的缺陷,那就是必须知道你要代理的那个类的具体类型,如果是一个继承类的话,我们之前的实现就出问题了。这个问题就是class count_point { friend class handle; point p;//这里
int count; count_point(); count_point(int x,int y); count_point(const count_point&);
};
|
现在如果我们把引用计数从count_point类中分离出来,也就是我们这样写handle类
class handle { public: handle(); handle(int x,int y); handle(const point&); handle(const handle&); handle& operator=(const handle&); ~handle(); private: point* ptr; int* u;//指向引用计数
}
|
使用了这个point的指针后我们就可以把这个handle绑定到不管是一个基类还是他的派生类,这是动态绑定的优点。这里我们发现舍去了之前我们写的count_point类,看上去简洁了很多,以后我们会回头来写一个辅助类。好了,现在要做的就是实现handle类
handle::handle():ptr(new point),u(new int(1)){}
handle::handle(int x,int y):ptr(new point(x,y)),u(new int(1)){}
handle::handle(const point&h):ptr(new point(h)),u(){}
handle::handle(const handle&h):ptr(h.p),u(h.u) { ++*u; }
handle::handle& operator=(const handle&h) { ++*h.u; if(--*u == 0){ delete u; delete ptr; } u = h.u; ptr = h.ptr; return *this; }
|
现在我们希望最好我们能把引用计数也抽象一下,应该怎么抽象呢?最好的就是用类类实现,把int*这个计数放到一个类里,这个类具有必要的初始化函数,拷贝构造函数,赋值操作符,析构函数,于是我们构造了这样的一个类
class usecount { public: usecount(); usecount(const usecount&); usecount& operator=(const usecount&); ~usecount(); private: int* p; }
|
按照惯例,现在我们要做的就是实现它
usecount::usecount():p(new int(1)){}
usecount::usecount(const usecount& h):p(h.p) {++*p;}
usecount::~usecount() { if(--*p == 0) delete p; }
|
注意我们没有实现赋值操作符,等下会解释为什么这么做,现在我们可以改写handle类了
class handle { public: handle(); handle(int x,int y); handle(const point&); handle(const handle&); handle& operator=(const handle&); ~handle(); private: point* ptr; usecount u;//改成这个 }
|
按照老习惯,接下来要实现这个类的成员函数
handle::handle():ptr(new point){}
handle::handle(int x,int y):ptr(new point(x,y)){}
handle::handle(const point&h):ptr(new point(h)){}
handle::handle(const handle&):ptr(h.ptr),u(h.u){}
handle::~handle() { if(--u == 0) delete ptr; }
|
恩,是时候交代一下我们为什么没有写operator=函数了,这个函数要做什么?他要对一个计数器加一,对另外一个减一,可能还要删除一个计数器,这些操作很可能改变引用计数,所以我们要在usecount类中添加一个额外的操作,我们命名为reattach,因为我们不定义operator=了,所以他应该在类中成为一个私有成员,现在看看reattach的实现
bool usecount::reattach(const usecount&h) { ++*h.p; if(--*p == 0){ delete p; p = h.p; return true; } p = h.p; return false;
}
|
现在我们可以定义handle的operator=了
handle::operator =(const handle& h) { if(u.reattach(h.u)) delete ptr; ptr = h.ptr; return *this; }
|