Qxt中的d-pointer技术及改进

来源:互联网 发布:软件模块结构图 编辑:程序博客网 时间:2024/05/21 23:04

Qxt是一个Qt的扩展库。其中也用到了d-pointer技术,但是与Qt的区别很大,比起Qt有点不足之处。这里我先简单看下它的实现,然后吸取Qt中的优点进行改进。(最新代码在 https://github.com/wang-bin/d-pointer )

之前写过一篇关于d-pointer的文章 http://blog.csdn.net/ibingow/article/details/7522157  ,这里很多细节就不重复了。

在qxtglobal.h中相关代码

/****************************************************************************** This file is derived from code bearing the following notice:** The sole author of this file, Adam Higerd, has explicitly disclaimed all** copyright interest and protection for the content within. This file has** been placed in the public domain according to United States copyright** statute and case law. In jurisdictions where this public domain dedication** is not legally recognized, anyone who receives a copy of this file is** permitted to use, modify, duplicate, and redistribute this file, in whole** or in part, with no restrictions or conditions. In these jurisdictions,** this file shall be copyright (C) 2006-2008 by Adam Higerd.****************************************************************************/#define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface<PUB, PUB##Private> qxt_d;#define QXT_DECLARE_PUBLIC(PUB) friend class PUB;#define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this);#define QXT_D(PUB) PUB##Private& d = qxt_d()#define QXT_P(PUB) PUB& p = qxt_p()template <typename PUB>class QxtPrivate{public:    virtual ~QxtPrivate()    {}    inline void QXT_setPublic(PUB* pub)    {        qxt_p_ptr = pub;    }protected:    inline PUB& qxt_p()    {        return *qxt_p_ptr;    }    inline const PUB& qxt_p() const    {        return *qxt_p_ptr;    }    inline PUB* qxt_ptr()    {        return qxt_p_ptr;    }    inline const PUB* qxt_ptr() const    {        return qxt_p_ptr;    }private:    PUB* qxt_p_ptr;};template <typename PUB, typename PVT>class QxtPrivateInterface{    friend class QxtPrivate<PUB>;public:    QxtPrivateInterface()    {        pvt = new PVT;    }    ~QxtPrivateInterface()    {        delete pvt;    }    inline void setPublic(PUB* pub)    {        pvt->QXT_setPublic(pub);    }    inline PVT& operator()()    {        return *static_cast<PVT*>(pvt);    }    inline const PVT& operator()() const    {        return *static_cast<PVT*>(pvt);    }    inline PVT * operator->()    {return static_cast<PVT*>(pvt);    }    inline const PVT * operator->() const    {return static_cast<PVT*>(pvt);    }private:    QxtPrivateInterface(const QxtPrivateInterface&) { }    QxtPrivateInterface& operator=(const QxtPrivateInterface&) { }    QxtPrivate<PUB>* pvt;};

具体不解释了,不难理解。使用时在类定义里加上

QXT_DECLARE_PRIVATE(MyClass)

就会给你生成一个类似于智能指针的成员变量qxt_d,它只是一个借口,真正存放数据的是MyClassPrivate这个类的指针pvt,继承自 QxtPrivate<MyClass>,在qxt_d构造时产生。

私有类的写法是

class MyClassPrivate : public QxtPrivate<MyClass>{....}

一个缺点是派生类不能直接访问基类的数据。可以在 Qxt的源码中看到qxt_d都声明为 private的,而且每个类都有这个成员,并且都是相互独立的,这个就显得有点奇怪了。Qt的做法是数据成员都可以在派生类中访问的,数据被声明为protected,并且Private类可以被继承。

另外一个缺点就是构造一个类可能会分配很多次内存。一个类的第N代派生类构造时会new N次,因为继承链上的每个类都要给自己的private类分配内存。

我对qxt的代码进行了修改,可以解决以上问题,并且使用也更简单。形式上类似于Qt。不详细解释了

//QxtPrivateInterface<PUB, PUB##Private> qxt_d;#define QXT_DECLARE_PRIVATE(PUB) \inline PUB##Private& d_func() { return qxt_d.pri<PUB##Private>(); } \inline const PUB##Private& d_func() const { return qxt_d.pri<PUB##Private>(); } \friend class PUB##Private;#define QXT_DECLARE_PUBLIC(PUB) \inline PUB& q_func() { return *static_cast<PUB*>(qxt_ptr()); } \inline const PUB& q_func() const { return *static_cast<PUB*>(qxt_ptr()); } \friend class PUB;#define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this);#define QXT_D(PUB) PUB##Private& d = qxt_d.pri<PUB##Private>()#define QXT_P(Class) Class& p = *static_cast<Class*>(qxt_ptr())//interfacetemplate <typename PUB>class QxtPrivate{public:
    virtual ~QxtPrivate() {}    inline void QXT_setPublic(PUB* pub) { qxt_p_ptr = pub; }protected:    inline PUB& qxt_p() { return *qxt_p_ptr; }    inline const PUB& qxt_p() const { return *qxt_p_ptr; }    inline PUB* qxt_ptr() { return qxt_p_ptr; }    inline const PUB* qxt_ptr() const { return qxt_p_ptr; }private:    PUB* qxt_p_ptr;};//interfacetemplate <typename PUB, typename PVT>class QxtPrivateInterface{    friend class QxtPrivate<PUB>;public:    QxtPrivateInterface(PVT* d):pvt(d) {}    QxtPrivateInterface():pvt(new PVT) {}    ~QxtPrivateInterface() {if (pvt) {delete pvt;pvt = 0;}    }    inline void setPublic(PUB* pub) { pvt->QXT_setPublic(pub); }    template <typename T>    inline T& pri() { return *reinterpret_cast<T*>(pvt); }    template <typename T>    inline const T& pri() const { return *reinterpret_cast<T*>(pvt); } //static cast requires defination of T    inline PVT& operator()() { return *static_cast<PVT*>(pvt); }    inline const PVT& operator()() const { return *static_cast<PVT*>(pvt); }    inline PVT * operator->() { return static_cast<PVT*>(pvt); }    inline const PVT * operator->() const { return static_cast<PVT*>(pvt); }private:    QxtPrivateInterface(const QxtPrivateInterface&);    QxtPrivateInterface& operator=(const QxtPrivateInterface&);    QxtPrivate<PUB>* pvt;};

使用如下:

对于祖先类Base,加上protected成员

class BasePrivate;class Base{public:Base();protected:Base(BasePrivate& d);virtual ~Base();QxtPrivateInterface<Base, BasePrivate> qxt_d;};

如有需要也可以加上宏QXT_DECLARE_PRIVATE(Base),提供访问私有类的简便方法

然后定义BasePrivate,继承自QxtPrivate<Base>

Base的派生类做法类似,只要再定义派生类相应的私有类

class DerivedPrivate : public BasePrivate{}

为减小内存分配次数,派生类中调用基类的构造函数可以使用proteced里的那个。



头文件下载(包含如何使用):http://download.csdn.net/detail/ibingow/4765462


原创粉丝点击