Chinaunix首页 | 论坛 | 博客
  • 博客访问: 554732
  • 博文数量: 92
  • 博客积分: 2511
  • 博客等级: 少校
  • 技术积分: 932
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-19 10:10
文章分类
文章存档

2011年(6)

2010年(27)

2009年(37)

2008年(22)

我的朋友

分类: C/C++

2008-10-22 21:55:42

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

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;
}

阅读(1455) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2008-10-27 12:01:26

神龙操作系统招志愿者(主站http://pos.kingofcoders.com,英文主站http://pos.petersoft.com),创立于1998年,它的起源是我的一个大二研究项目,它的作者就是我Peter (mcheung63@hotmail.com).研目目的是创立一个能够在x86电脑上运行的操作系统,在经过漫长的个人学习期后,现在总算去到一个比较快速开发的阶段. 最开头是以masm作为编译工具,因为第一次学写汇编是学masm的.后来慢慢地把整个os项目移到linux上编译,现在使用的的编译工具为make nasm gcc,至于版本方面, gcc不要旧过2.95.2, nasm的话就很多版本也可以通过.现在在cygwin也可以完成整个编译,但首先要在cygwin建立i386-elf的toolchain,如果不懂,可以看看这个教程http:/ /forum2.kingofcoders.com/viewthread.php?tid=206&extra=page=1 现在pos还没可以作c语言的单步调试,原因是我不想把内核改成multiboot格式,因为pos的内核