C++ 句柄类

来源:互联网 发布:网络包工头在哪找活 编辑:程序博客网 时间:2024/05/16 05:34

一、容器与继承

    在容器中保存有继承关系的对象时,如果定义成保存基类对象,则派生类将被切割,如果定义成保存派生类对象,则保存基类对象又成问题(基类对象将被强制转换成派生类对象,而派生类中定义的成员未被初始化)。

    唯一的可行的选择是容器中保存对象的指针。但是需要用户管理对象和指针。C++中一个通用的技术是包装类(cover)或句柄类(handle)。用句柄类存储和管理类指针。

     句柄类大体上完成两方面的工作:

  1. 管理指针,这与智能指针的功能类似。

  2. 实现多态,利用动态绑定,是得指针既可以指向基类,也可以指向派生类。

     包装了继承层次的句柄有两个重要的设计考虑因素:

  1. 像对任何保存指针的类一样,必须确定对复制控件做些什么。包装了继承层次的句柄通常表现得像一个智能指针或者像一个值。

  2. 名柄类决定句柄接口屏蔽还是不屏蔽继承层次,如果不屏蔽继承层次,用户必须了解和使用基本层次中的对象(objects in theunderlying hierarchy)。

下面通过一个我自己写的一个简单的例子来说明这个问题:

    这个例子程序包括一个基类,一个派生类,还有一个句柄类。

    其中,基类有2个私有成员,数值m_base和程序名字name。派生类有一个新的私有成员,m_der。

    派生类和基类有虚函数compute。基类的compute它计算基类成员m_base平方。派生类的compute计算m_base平方和m_der之和。

    句柄类有两个数据成员,分别是指向引用计数的指针( 这里必须是指针,复制时引用计数复制指针的值,保证一个实例化对象只有一个引用计数)和指向基类或者是其派生类的指针。

复制代码
#include<iostream>#include<string>#include<exception>using namespace std;// base classclass Base {public:    //basic constructor    Base(int m_base = 1, string name = "Base")            : m_base(m_base), name(name) {        cout << "Base constructor called!" << endl;    }    //copy constructor    Base(const Base &base) : Base(base.m_base, base.name) {        cout << "Base copy called" << endl;    }    virtual Base *clone() const {        return new Base(*this);    }    const string getName() {        return name;    }    virtual int compute() const {        return m_base * m_base;    }    virtual ~Base(){        cout<<"Base deleted"<<endl;    }protected:    int m_base;    string name;};class Derived : public Base {public:    //basic constructor    Derived(int m_base, string name, int m_der)            : Base(m_base, name), m_der(m_der) {        cout << "Derived constructor called" << endl;    }    //copy constructor    Derived(const Derived &derived) : Derived(derived.m_base, derived.name, derived.m_der) {        cout << "Derived copy called" << endl;    }    virtual Derived *clone() const {        return new Derived(*this);    }    virtual int compute() const {        //调用父类中定义的方法        return Base::compute() + m_der;    }    virtual ~Derived(){        cout<<"Derived deleted"<<endl;    }private:    int m_der;};class Handler {public:    //默认构造函数    Handler() : pBase(NULL), use(new int(1)) { }    //一般构造函数    Handler(const Base &item) : pBase(item.clone()), use(new int(1)) { }    //复制构造函数    //每复制一次,引用计数就加1    Handler(const Handler &ref) : pBase(ref.pBase), use(ref.use) {        ++*use;    }    //重载赋值操作符    Handler &operator=(const Handler &right) {        ++*(right.use);        decrese_use();        pBase = right.pBase;        use = right.use;        return *this;    }    //重载箭头操作符    const Base *operator->() const {        if (pBase)            return pBase;        else            throw logic_error("unbound Handler!");    }    //重载解引用操作符    const Base &operator* () const{        if(pBase)            return *pBase;        else            throw logic_error("unbound Handler");    }    void print_use() {        cout << pBase->getName() << " use: " << *use << endl;    }    //析构函数    ~Handler() {        decrese_use();    }private:    //此处必须使用指针,保证一个Base实例只对应一个引用计数    int *use;    Base *pBase;    void decrese_use() {        if (--*use == 0) {            cout << pBase->getName() << " is going to be deleted!" << endl;            delete pBase;        }    }};int main() {    Handler h1(Base(2,"Base"));    h1.print_use();    cout<<"Base compute:"<<(*h1).compute()<<endl;    Handler h2(h1);    h2.print_use();    cout<<"Base compute:"<<(*h2).compute()<<endl;    cout<<"-------------------------------------"<<endl;    Handler h3(Derived(3,"derived",3));    h1=h3;    h1.print_use();    cout<<"Derived compute:"<<(*h1).compute()<<endl;    cout<<"system automatic delete begin"<<endl;    return 0;}
复制代码

二、句柄类

    句柄类Handle 有3个构造函数:默认构造函数,复制构造函数,和接收基类Base对象的构造函数。为了保证 在接收基类Base对象的构造函数中 复制具体对象的时候实现动态调用,得到正确类别的实例,我们在类中定义了虚函数clone

Base

virtual Base *clone() const {        return new Base(*this);}

Derived

virtual Derived *clone() const {        return new Derived(*this);}

三、运行结果   

主函数调用:

复制代码
int main() {    Handler h1(Base(2,"Base"));    h1.print_use();    cout<<"Base compute:"<<(*h1).compute()<<endl;    Handler h2(h1);    h2.print_use();    cout<<"Base compute:"<<(*h2).compute()<<endl;    cout<<"-------------------------------------"<<endl;    Handler h3(Derived(3,"derived",3));    h1=h3;    h1.print_use();    cout<<"Derived compute:"<<(*h1).compute()<<endl;    cout<<"system automatic delete begin"<<endl;    return 0;}
复制代码

输出:

复制代码
Base constructor called!Base constructor called!Base copy calledBase deletedBase use: 1Base compute:4Base use: 2Base use: 2Base compute:4-------------------------------------Base constructor called!Derived constructor calledBase constructor called!Derived constructor calledDerived copy calledDerived deletedBase deletedderived use: 2derived use: 2Derived compute:12system automatic delete beginBase is going to be deleted!Base deletedderived is going to be deleted!Derived deletedBase deleted
复制代码

  主函数中使用Base对象创建了Handler对象h1,并由h1构造Handler对象h2,通过输出可以发现Handler对象的引用计数由1变为2。然后使用Derived对象创建Handler对象h3,并将其赋值给h1,对h1,h3 输出其引用计数,可知引用计数均为2.



转载自:C++ 句柄类