总结网上看到的文章,使用D指针的好处如下:
1.保证代码的二进制兼容性;
2.隐藏实现细节;
3.提高编译速度;
Qt关于D指针和Q指针的定义:
d_ptr指针指向私有实现类,使用如下宏定义辅助函数和声明友元类
#define Q_DECLARE_PRIVATE(Class) /
inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } /
inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } /
friend class Class##Private;
q_ptr指针指向父类,使用如下宏定义辅助函数和声明友元类
#define Q_DECLARE_PUBLIC(Class) /
inline Class* q_func() { return static_cast<Class *>(q_ptr); } /
inline const Class* q_func() const { return static_cast<const Class *>(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 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 <QObject>
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 <QtDebug>
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_ptr的声明看起来不够简洁;
问题改进:
1.使用QScopedPointer,不用关注D指针的释放;
2.使用宏改进使用;
#define DQ_DECLARE_PRIVATE(Class) \
Q_DECLARE_PRIVATE(Class) \
QScopedPointer<Class##Private> 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 <QtGlobal>
#include <QScopedPointer>
#define DQ_DECLARE_PRIVATE(Class) \
Q_DECLARE_PRIVATE(Class) \
QScopedPointer<Class##Private> 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 <QObject>
#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 <QtDebug>
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;
}