句柄类(二)
帐 号: 注册帐号
密 码:  找回密码
      记住用户名和密码
句柄类(二)

在我的前一篇博文里,我们讨论了有关句柄类的实现,这个句柄类有一个明显的缺陷,那就是必须知道你要代理的那个类的具体类型,如果是一个继承类的话,我们之前的实现就出问题了。这个问题就是

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(--*== 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(--*== 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(--== 0)
        delete ptr;
}

恩,是时候交代一下我们为什么没有写operator=函数了,这个函数要做什么?他要对一个计数器加一,对另外一个减一,可能还要删除一个计数器,这些操作很可能改变引用计数,所以我们要在usecount类中添加一个额外的操作,我们命名为reattach,因为我们不定义operator=了,所以他应该在类中成为一个私有成员,现在看看reattach的实现

bool usecount::reattach(const usecount&h)
{
    ++*h.p;
    if(--*== 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;
}

copyright:2016-2020|邮箱:imalib@vip.163.com

蜀ICP备16020986号