学习记录-Qt中使用Q指针和D指针

 

总结网上看到的文章,使用D指针的好处如下:

1.保证代码的二进制兼容性;

2.隐藏实现细节;

3.提高编译速度;

Qt关于D指针和Q指针的定义:

d_ptr指针指向私有实现类,使用如下宏定义辅助函数和声明友元类

#define Q_DECLARE_PRIVATE(Class) /  
    inline Class##Private* d_func() { return reinterpret_cast(qGetPtrHelper(d_ptr)); } /  
    inline const Class##Private* d_func() const { return reinterpret_cast(qGetPtrHelper(d_ptr)); } /  
    friend class Class##Private; 

 q_ptr指针指向父类,使用如下宏定义辅助函数和声明友元类

#define Q_DECLARE_PUBLIC(Class)                                    /  
    inline Class* q_func() { return static_cast(q_ptr); } /  
    inline const Class* q_func() const { return static_cast(q_ptr); } /  
    friend class Class;  

 使用D指针和Q指针的宏定义

#define Q_D(Class) Class##Private * const d = d_func()  
#define Q_Q(Class) Class * const q = q_func()  

 

/*
   Some classes do not permit copies to be made of an object. These
   classes contains a private copy constructor and assignment
   operator to disable copying (the compiler gives an error message).
*/
#define Q_DISABLE_COPY(Class) \
    Class(const Class &) Q_DECL_EQ_DELETE;\
    Class &operator=(const Class &) Q_DECL_EQ_DELETE;

定义一个类如下:

class TestClassPrivate;
class TestClass
{
public:
    TestClass();
    ~TestClass();

private:
    TestClassPrivate * const d_ptr;
    Q_DECLARE_PRIVATE(TestClass);
};

 

定义一个私有类如下:

class TestClass;
class TestClassPrivate
{
public:
    TestClassPrivate(TestClass *q);

private:
    TestClass * const q_ptr;
    Q_DECLARE_PUBLIC(TestClass);
    
    int m_val1;
};

一个实例:

testclass.h

#ifndef TESTCLASS_H
#define TESTCLASS_H

#include 

class TestClassPrivate;
class TestClass
{
public:
    explicit TestClass(QObject *parent);
    ~TestClass();
    
    void doFunc();
    
private:
    void showMsg(QString str);
    
private:
    TestClassPrivate * const d_ptr;
    Q_DECLARE_PRIVATE(TestClass);
    Q_DISABLE_COPY(TestClass);
};

#endif // TESTCLASS_H

testclass.cpp

#include "testclass.h"
#include 

class TestClassPrivate
{
public:
    TestClassPrivate(TestClass *q) :
        q_ptr(q)
    {
    }

    void testFunc()
    {
        Q_Q(TestClass);
        q->showMsg("hello!");
    }

private:
    TestClass * const q_ptr;
    Q_DECLARE_PUBLIC(TestClass);
};


TestClass::TestClass(QObject *parent):
    d_ptr(new TestClassPrivate(this))
{

}

TestClass::~TestClass()
{
    Q_D(TestClass);
    delete d;
}

void TestClass::doFunc()
{
    Q_D(TestClass);
    d->testFunc();
}

void TestClass::showMsg(QString str)
{
    qDebug() << str;
}

以上是使用Qt自带宏实现。

 存在问题:

1.d_ptr需要手动释放,有可能粗心忘记了;

2.d_ptr和q_pt的声明看起来不够简洁;

问题改进:

1.使用QScopedPointer,不用关注D指针的释放;

2.使用宏改进使用;

#define DQ_DECLARE_PRIVATE(Class) \
    Q_DECLARE_PRIVATE(Class) \
    QScopedPointer d_ptr;

#define DQ_DECLARE_PUBLIC(Class) \
    Q_DECLARE_PUBLIC(Class) \
    Class* q_ptr;

#define DQ_SAFE_DELETE(p) do { if(p) { delete (p); (p) = 0; } } while(0)

使用实例:

dqglobal.h

#ifndef DQGLOBAL_H
#define DQGLOBAL_H

#include 
#include 

#define DQ_DECLARE_PRIVATE(Class) \
    Q_DECLARE_PRIVATE(Class) \
    QScopedPointer d_ptr;

#define DQ_DECLARE_PUBLIC(Class) \
    Q_DECLARE_PUBLIC(Class) \
    Class* q_ptr;

#define DQ_SAFE_DELETE(p) do { if(p) { delete (p); (p) = 0; } } while(0)

#endif // DQGLOBAL_H

testclass.h

#ifndef TESTCLASS_H
#define TESTCLASS_H

#include 
#include "dqglobal.h"

class TestClassPrivate;
class TestClass
{
    DQ_DECLARE_PRIVATE(TestClass)
public:
    explicit TestClass(QObject *parent);
    ~TestClass();

    void doFunc();

private:
    void showMsg(QString str);

//private:
//    TestClassPrivate * const d_ptr;
//    Q_DECLARE_PRIVATE(TestClass);
//    Q_DISABLE_COPY(TestClass);
};

#endif // TESTCLASS_H

testclass.cpp

#include "testclass.h"
#include 

class TestClassPrivate
{
    DQ_DECLARE_PUBLIC(TestClass)
public:
    TestClassPrivate(TestClass *q) :
        q_ptr(q)
    {
    }

    void testFunc()
    {
        Q_Q(TestClass);
        q->showMsg("hello!");
    }

//private:
//    TestClass * const q_ptr;
//    Q_DECLARE_PUBLIC(TestClass);
};


TestClass::TestClass(QObject *parent):
    d_ptr(new TestClassPrivate(this))
{

}

TestClass::~TestClass()
{
//    Q_D(TestClass);
//   delete d;
}

void TestClass::doFunc()
{
    Q_D(TestClass);
    d->testFunc();
}

void TestClass::showMsg(QString str)
{
    qDebug() << str;
}

 

你可能感兴趣的:(Qt)