第七章:句柄类第二部分
6章:向类中添加句柄和引用计数的技术,能通过控制引用计数就能高效的“复制“该类的对象。
缺点:必须定义一个具有类型相同的成员的新类。会困难当绑定这样的句炳到一个继承自T的(静态的)未知类的对象时。
新方法思想:将引用计数从数据中分离出来,引用计数放到它自己的对象中。
7-1回顾
class Point{
public:
Point():xval(0),yval(0) {}
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;
};
class UPoint {
// 所有成员都是私有的
friend class Handle;
Point p;
int u;
UPoint() :u(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;
}
7-2分离引用计数
class Handle {
public:
//和前面一样
private:
Point* p;
int *u; //指向引用计数的指针
};
为什么使用Point*而不是Upoint*?
Handle::Handle():u(new int(1)), p(new Point) {}
Handle::Handle(int x, int y):u(new int(1), p(new Point(x, y)){}
Handle::Handle(const Point& p0):u(new int(1)),p(new Point(p0)) {}
Handle::Handle(const Handle& h):u(h.u), p(h.p) {++*u;};
Handle& operator=(const Handle& h)
{
++*h.u;
if(--*u) ==0)
delete u;
delete p;
}
u = h.u;
p = h.p;
return *this;
}
Handle::~Handle()
{
if(--*u == 0) {
delete u;
delete p;
}
}
缺点:new和delete要成双成对的出现:一个处理引用计数,一个处理数据。问题:有没有一种方法能抽象化我们关于引用计数的工作呢?
7-3 对引用计数的抽象
为了避免日后一次次重写,尤其是假设引用技术类对句柄将要绑定的哪个对象的特性一无所知。
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& u):p(u.p) {++*p; }
UseCount::~UseCount() if(--*p ==0) delete p; } //我感觉不对?
//重写handle
class Handle {
public:
//和前面一样
private:
Point *p;
UseCount u;
};
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) {}
class UseCount {
//和前面一样
public:
bool only();
};
bool UseCount::only() { return *p ==1; }
Handle::~Handle()
{
if(u.only())
delete p;
}
Handle 赋值操作符情况又如何?它需要类UseCount不直接支持的操作:对计数器增1,另一个减1,删除一个计数器,还要决定是否删除已赋值的数据。
为什么要私有化对UseCount对象的设置?(因为不需要这样的操作,没有用上)
class UseCount {
//和前面一样
public:
bool reattach(const UseCount&);
private:
UseCount& operator= (const UseCount& u);
};
bool UseCount::reattach(const UseCount& u)
{
++*u.p;
if(--*p==0) {
delete p;
p = u.p;
return true;
}
p =u.p;
return false;
}
Handle& Handle::operator=(const Handle& h)
{
if(u.reattach(h.u))
delete p;
p =h.p;
return *this;
}
7-4存取函数和写时复制
对Point对象的单个元素的读取和写入了。我们将通过写时复制来实现值语义。要确定它的句柄是当前唯一使用该特定Poing 对象的句柄。UseCount::only帮助我们查出某个句柄是否是当前唯一使用这个句柄对象的句柄。
class UseCount {
//和前面的一样
public:
bool makeonly();
};
bool UseCount::makeonly() {
if(*p == 1)
return false;
--*p;
p = new int(1);
return true;
}
int Handle::x() const {
return p->x();
}
Handle& Handle::x(int x0) {
if(u.makeonly() )
p= new Point(*p);
p->x(x0);
return *this;
}
7-5 讨论
这个例子中功能的划分好象好奇特(看不出。道行太浅)。 好几种情况下,类Handel 都请求类UseCount来做某些时,然后不厌其烦的再次要求做几乎相同的事情(看不出)。
举个例子:Handle::x存取函数使用makeonly来确保引用计数(use count)为1, 如果计数器被复制(因而makeonly返回true), 则复制底层的Point对象。这两项任务可以合并?(怎样合并?)
我们这样做的优势:UseCount类可以在不了解其使用者任何信息的情况下与之合为一体。
UseCount类简化了一个实现中的特定子问题:它不打算为终端用户所用。不过整体上:一个相当繁杂的问题的解决方案被清晰的分割界定了。另外,最后获得的Handle类跟那些以传统方式构件起来的类一样容易使用,并且更加灵活。
(现在我由于缺乏编程经验,只能读一知半,不能举一反三,希望努力勤奋能改变这样的境况)
本章代码调试:基本没有遇到什么困难.有空在深入思考.彻底理解句柄类.
#include
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;
};
class UseCount {
public:
UseCount();
UseCount(const UseCount&);
// UseCount& operator=(const UseCount&);
~UseCount();
int p1() {return *p;};
//其他需要决定的内容
bool only();
bool reattach(const UseCount&);
bool makeonly();
private:
UseCount& operator= (const UseCount& u);
int *p;
};
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::makeonly() {
if(*p == 1)
return false;
--*p;
p = new int(1);
return true;
}
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);
int num() {return u.p1();};
private:
Point *p;
UseCount u;
};
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;
}
int Handle::x() const {
return p->x();
}
Handle& Handle::x(int x0) {
if(u.makeonly() )
p= new Point(*p);
p->x(x0);
return *this;
}
int main()
{
Handle a(3, 4);
Handle b;
b=a;
Handle c=a;
Handle d=b;
// delete d;
cout<//3
cout<//3
cout<//输出为4;
}
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/409557/viewspace-891805/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/409557/viewspace-891805/