通过多方查阅资料,普遍认为Qt引入D指针和Q指针一方面是为了数据封装实现隐藏,另一方面是为了解决二进制兼容问题,避免因改变类的私有数据重新编译库的问题。
d_ptr.h
#ifndef D_PTR_H
#define D_PTR_H
#include <QObject>
template <typename T>
static inline T *GetPtrHelper(T *ptr) { return ptr; }
#define DECLARE_PRIVATE(Class) \
inline Class##Private* d_func() { return reinterpret_cast<Class##Private*>(GetPtrHelper(d_ptr)); } \
inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private*>(GetPtrHelper(d_ptr)); }\
friend class Class##Private;
#define DPTR(Class) Class##Private * const d = d_func()
class MyClassPrivate;
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = 0);
virtual ~MyClass();
void testFunc();
protected:
MyClass(MyClassPrivate &d);
private:
DECLARE_PRIVATE(MyClass)
MyClass(const MyClass&);
MyClass& operator= (const MyClass&);
MyClassPrivate * const d_ptr;
};
#endif // D_PTR_H
d_ptr.cpp
include "d_ptr.h"
#include "d_ptr.h"
#include "q_ptr.h"
MyClass::MyClass(QObject *parent) :
QObject(parent),
d_ptr(new MyClassPrivate(this))
{
}
MyClass::~MyClass()
{
DPTR(MyClass);
delete d;
}
void MyClass::testFunc()
{
DPTR(MyClass);
d->fool();
}
q_ptr.h
#ifndef Q_PTR_H
#define Q_PTR_H
#include <QObject>
#include "d_ptr.h"
#define 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;
#define QPTR(Class) Class * const q = q_func()
class MyClassPrivate : public QObject
{
Q_OBJECT
public:
MyClassPrivate(MyClass *q, QObject *parent = 0);
virtual ~MyClassPrivate() {}
signals:
void testSgnl();
private slots:
void testSlt();
public:
void fool();
private:
DECLARE_PUBLIC(MyClass)
MyClass * const q_ptr;
};
#endif // Q_PTR_H
q_ptr.cpp
#include "q_ptr.h"
MyClassPrivate::MyClassPrivate(MyClass *q, QObject *parent) :
QObject(parent), q_ptr(q)
{
connect(this, SIGNAL(testSgnl()), this, SLOT(testSlt()));
}
void MyClassPrivate::fool()
{
emit testSgnl();
}
void MyClassPrivate::testSlt()
{
printf("This is a pimpl pattern sample implemented in qt's \"d_ptr, q_ptr\" way\n");
}
main.cpp
#include "q_ptr.h"
int main(/*int argc, char *argv[]*/)
{
MyClass * d_ptr = new MyClass;
d_ptr->testFunc();
delete d_ptr;
// while(1);
return 0;
}