首先是Q_D指针:先贴上我们的测试用例.
class TEST;
class TESTPrivate
{
public:
TESTPrivate(TEST *parent):q_ptr(parent),a(666)
{cout << "TESTPrivate" << endl;}
~TESTPrivate()
{cout << "~TESTPrivate" << endl;}
private:
Q_DECLARE_PUBLIC(TEST)
private:
TEST *q_ptr;
int a;
};
class TEST
{
public:
TEST():d_ptr(new TESTPrivate(this)),b(2){}
~TEST(){delete d_ptr;}
int getValue()
{
Q_D(TEST);
return d->a;
}
private:
int b;
TESTPrivate *d_ptr;
Q_DECLARE_PRIVATE(TEST)
};
int main(int /*argc*/, char */*argv*/[])
{
TEST t;
cout << t.getValue() << endl;
}
查看这里面定义的宏:
#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;
#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;
现在,我们手动进行一次宏展开:
// Q_DECLARE_PUBLIC(TEST)
inline TEST* q_func() { return static_cast(q_ptr); }
inline const TEST* q_func() const { return static_cast(q_ptr); }
friend class TEST;
// Q_DECLARE_PRIVATE(TEST)
inline TESTPrivate* d_func() { return reinterpret_cast(qGetPtrHelper(d_ptr)); }
inline const TESTPrivate* d_func() const { return reinterpret_cast(qGetPtrHelper(d_ptr)); }
friend class TESTPrivate;
从这里可以看到,实际上宏只是互相声明了友元,并返回了d_ptr指针.
我们查看以下Q_D宏.可以看到这里定义了d指针与q指针.
#define Q_D(Class) Class##Private * const d = d_func()
宏展开,可以看到,所谓的d指针只是获得类Q_DECLARE_PRIVATE(TEST)中函数的返回值:
// Q_D(TEST);
TESTPrivate * const d = d_func();
在Q_DECLARE_PRIVATE(TEST)中,查看qGetPtrHelper的宏:
template static inline T *qGetPtrHelper(T *ptr) { return ptr; }
d指针我们可以不调用d_func(),直接从d_ptr那里获得一份拷贝,并删除多余的func函数,最终结果如下:
class TEST;
class TESTPrivate
{
public:
TESTPrivate(TEST *parent):q_ptr(parent),a(666)
{cout << "TESTPrivate" << endl;}
~TESTPrivate()
{cout << "~TESTPrivate" << endl;}
private:
friend class TEST;
TEST *q_ptr;
int a;
};
class TEST
{
public:
TEST():d_ptr(new TESTPrivate(this)),b(2),c(3){}
~TEST(){delete d_ptr;}
int getValue()
{
TESTPrivate *d = d_ptr;
return d->a;
}
private:
int b;
TESTPrivate *d_ptr;
friend class TESTPrivate;
};
Q_Q指针与Q_D指针类似,在原理上是一致的.只是在概念中用法不一样.Q_D指针一般用来访问"Private"类中的数据,Q_Q指针则是通过Private类访问"Public"类.private类就是装钱的钱包,public类就是口袋.Qt里面如此封装,应该是尽量降低对OO的破坏吧!毕竟friend本身就违背类OO原则.