zoukankan      html  css  js  c++  java
  • 句柄类

    句柄类

             ——《C++沉思录》第六章 句柄:第一部分

             三个类:

             Point:主体类,表示实际的数据

             Handle:句柄类,用来引用代理主体类

             UPoint:对Point的封装,增加了一个use count成员,用来记录主体类对象被引用代理的次数。该类完全可以省略,但是添加此类的好处是更便于管理。

             对Handle的拷贝构造函数和赋值运算符的实现是通过对UPoint对象的use count修改来完成的。Handle中有两个写函数,有两种实现方式:指针语义和值语义,这里涉及了一项技术称作写时赋值(copy on write)。

             具体代码如下:

    // 句柄类
    #include <iostream>
    using namespace std;
    
    class Point
    {
    private:
        int xval;
        int yval;
    
    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; }
    };
    
    // use count class
    class UPoint
    {
    private:
        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
    {
    private:
        UPoint* up;
    
    public:
        Handle();
        Handle(int, int);
        Handle(const Point&);
        Handle(const Handle&);
        Handle& operator = (const Handle&);
        ~Handle();
    
        int x() const;
        int y() const;
    
        Handle& x(int);
        Handle& y(int);
    
        void test() const;
    };
    
    void Handle::test() const
    {
        cout << up->u << endl;
    }
    
    Handle::Handle() : up(new UPoint) {}
    
    Handle::Handle(int x, int y) : up(new UPoint(x, y)) {}
    
    Handle::Handle(const Point& p) : up(new UPoint(p)) {}
    
    Handle::~Handle()
    {
        if (--up->u == 0)
        {
            delete up;
        }
    }
    
    Handle::Handle(const Handle& h) : up(h.up) { ++up->u; }
    
    Handle& Handle::operator = (const Handle& h)
    {
        // 为了避免当只存在一个引用的时候,自赋值操作而引起的错误,
        // 这里采用先递增右侧句柄的引用计数,然后再对左侧句柄引用计数进行递减
        ++h.up->u;
        
        if (--up->u == 0)
        {
            delete up;
        }
        up = h.up;
        return *this;
    
        // 对于operator=的操作也可以采用另外一种方法:
        // 先检测是否是自赋值,如果是,则不进行操作,直接返回*this
        // 如果不是,则--up->u,然后++h.up->u
    }
    
    int Handle::x() const { return up->p.x(); }
    int Handle::y() const { return up->p.y(); }
    
    // 对Handle& Handle::x(int)和Handle& Handle::y(int)的实现有两种方式:
    // 指针语义和值语义
    // 其中值语义的实现方式称作为写时赋值(copy on write)
    
    // 指针语义
    Handle& Handle::x(int x0)
    {
        up->p.x(x0);
        return *this;
    }
    
    Handle& Handle::y(int y0)
    {
        up->p.y(y0);
        return *this;
    }
    
    //// 值语义
    //Handle& Handle::x(int x0)
    //{
    //    if (up->u > 1)
    //    {
    //        --up->u;
    //        up = new UPoint(up->p);
    //    }
    //    up->p.x(x0);
    //
    //    return *this;
    //}
    //
    //Handle& Handle::y(int y0)
    //{
    //    if (up->u > 1)
    //    {
    //        --up->u;
    //        up = new UPoint(up->p);
    //    }
    //    up->p.y(y0);
    //
    //    return *this;
    //}
    
    int main()
    {
        Point p1;
        Handle* ph1 = new Handle(p1);
    
        ph1->test();
    
        Handle* ph2 = new Handle(*ph1);
    
        ph1->test();
        ph2->test();
    
        delete ph1;
    
        ph2->test();
        
        return 0;
    }

  • 相关阅读:
    github教程
    Django订单接入支付宝
    python去除html标签的几种方法
    vue-cli项目生成
    restful设计规范
    Vue的指令系统、计算属性和表单输入绑定
    Vue工具
    药物不良反应数据库信息的下载
    爬虫案例之Pubmed数据库下载
    数据分析案例之39药品网
  • 原文地址:https://www.cnblogs.com/unixfy/p/3453728.html
Copyright © 2011-2022 走看看