• 【C++沉思录】句柄2


    1、【C++沉思录】句柄1 存在问题:
    句柄为了绑定到Point的对象上,必须定义一个辅助类UPoint,如果要求句柄绑定到Point的子类上,那就存在问题了。
    2、有没有更简单的办法呢?
    句柄使用Point*直接绑定到Point对象上(包括子类),为了保持多个句柄引用计数的一致性,使用int* 指向引用计数。
    3、代码如下:
    #include "point.h"
    class Handle_2
    {
    public:
    Handle_2():_p(new Point),_u(new int(1)){}

    Handle_2(int x,int y):_p(new Point(x,y)),_u(new int(1)){}

    Handle_2(const Point& rhs):_p(new Point(rhs)),_u(new int(1)){}

    ~Handle_2()
    {
    subRef();
    }

    Handle_2(const Handle_2& rhs)
    {
    addRef(rhs);
    }

    Handle_2& operator=(const Handle_2& rhs)
    {
    if(this != &rhs)
    {
    subRef();
    addRef(rhs);
    }

    return * this;
    }


    int GetX()
    {
    return _p->GetX();
    }

    int GetY()
    {
    return _p->GetY();
    }

    Handle_2& SetX(int x)
    {
    if(*_u == 1) // 当前是唯一的引用
    {
    _p->SetX(x);
    }
    else
    {
    --*_u;
    _p = new Point(x,_p->GetY());
    }
    return *this;
    }

    Handle_2& SetY(int y)
    {
    if(*_u == 1) // 当前是唯一的引用
    {
    _p->SetY(y);
    }
    else
    {
    --*_u;
    _p = new Point(_p->GetX(),y);
    }
    return *this;
    }

    private:
    void addRef(const Handle_2& rhs) // 复制对象指针和引用计数指针,增加引用
    {
    _p = rhs._p;
    _u = rhs._u;
    ++*_u;
    }

    void subRef()// 减少引用,判断是否delete对象和引用计数
    {
    if(--*_u == 0)
    {
    delete _p;
    delete _u;
    }
    }

    private:
    Point* _p;
    int* _u;
    };
    4、这里要手动管理动态内存 int* _u; 同样道理,可以使用栈上对象进行管理,抽象出一个辅助类 UseCount
    class UseCount
    {
    public:
    UseCount():_p(new int(1)){}
    UseCount(const UseCount& rhs)
    {
    addRef(rhs);
    }

    UseCount& operator=(const UseCount& rhs)
    {
    if(this != &rhs)
    {
    subRef();
    addRef(rhs);
    }
    return *this;
    }

    ~UseCount()
    {
    subRef();
    }

    bool IsOnly()
    {
    return (*_p == 1);
    }

    void MakeOnly()
    {
    if(IsOnly()) // 防止已经是only,用户还调用MakeOnly
    {
    return;
    }
    --*_p;
    _p = new int(1);
    }

    private:
    void addRef(const UseCount& rhs)
    {
    _p = rhs._p;
    ++*_p;
    }

    void subRef()
    {
    if(--*_p == 0)
    {
    delete _p;
    }
    }

    private:
    int* _p;
    };

    #include "point.h"
    #include "use_count.h"
    class Handle_2
    {
    public:
    Handle_2():_p(new Point){}

    Handle_2(int x,int y):_p(new Point(x,y)){}

    Handle_2(const Point& rhs):_p(new Point(rhs)){}

    ~Handle_2()
    {
    subRef();
    }

    Handle_2(const Handle_2& rhs)
    {
    addRef(rhs);
    }

    Handle_2& operator=(const Handle_2& rhs)
    {
    if(this != &rhs)
    {
    subRef();
    addRef(rhs);
    }

    return * this;
    }


    int GetX()
    {
    return _p->GetX();
    }

    int GetY()
    {
    return _p->GetY();
    }

    Handle_2& SetX(int x)
    {
    if(_u.IsOnly()) // 当前是唯一的引用
    {
    _p->SetX(x);
    }
    else
    {
    _u.MakeOnly();
    _p = new Point(x,_p->GetY());
    }
    return *this;
    }

    Handle_2& SetY(int y)
    {
    if(_u.IsOnly()) // 当前是唯一的引用
    {
    _p->SetY(y);
    }
    else
    {
    _u.MakeOnly();
    _p = new Point(_p->GetX(),y);
    }
    return *this;
    }

    private:
    void addRef(const Handle_2& rhs)
    {
    _p = rhs._p;
    _u = rhs._u;
    }

    void subRef()
    {
    if(_u.IsOnly())
    {
    delete _p;
    }
    }

    private:
    Point* _p;
    UseCount _u;
    };

  • 相关阅读:
    js 导航栏多项点击显示下拉菜单代码
    当你工作与生活迷茫时可以来看看 shuke
    vs code使用指南
    两列
    三列浮动中间宽度自适应
    两列右列宽度自适应
    word文档巧替换(空行替换、空格替换、软回车替换成硬回车)
    统计单元格内指定的字符数方法 ,方法 一好用
    umi ui 构建时出现 spawn sh ENOENT 报错的解决方法
    新的博客,声明一下以前的域名作废了
  • 原文地址:https://www.cnblogs.com/nzbbody/p/4678658.html
Copyright © 2020-2023  润新知