在源码中,我们会经常看到Q_Q 和 Q_D 这两个东西 ,很好奇,就去网上搜索了一些和 查看了一些源码 部分
一:Q_D相关宏
#define Q_D(Class) Class##Private * const d = d_func()
Q_D(Test);
//展开后 是一个 私有类的指针常量
TestPrivate * const d = d_func();
有人不知道“##” 是什么意思,其实就是一个连接符 将A##B -》 AB 组成一个新的字符串名称
Q_DECLARE_PRIVATE(Class)
#define Q_DECLARE_PRIVATE(Class) \
inline Class##Private* d_func() \
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
inline const Class##Private* d_func() const \
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
friend class Class##Private;
Q_DECLARE_PRIVATE(Test)
//展开后
inline TestPrivate* d_func() {return reinterpret_cast<TestPrivate *>(qGetPtrHelper(d_ptr));}
inline const TestPrivate* d_func() const{return reinterpret_cast<const TestPrivate *>(qGetPtrHelper(d_ptr));}
friend class TestPrivate;
d_ptr 指针:在主类里面写,来访问我们的私有类
二:Q_Q相关宏
#define Q_Q(Class) Class * const q = q_func()
Q_Q(Test);
//展开后
Test* const q = q_func();
Q_DECLARE_PUBLIC(Class)
#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;
Q_DECLARE_PUBLIC(Test)
//展开后:
inline Test* q_func() { return static_cast<Test*>(q_ptr); }
inline const Test* q_func() const { return static_cast<const Test*>(q_ptr); }
friend class Test;
q_ptr 指针:在私有类 里面写,来访问我们的主类
使用这两个指针的好处:
1.保证代码的二进制兼容性;
二进制兼容性:动态链接到库的前一个版本的程序继续与库的新版本一起运行而不需要重新编译,则库是二进制兼容的。
要能够实现二进制兼容,就要求每一个结构以及每一个对象的数据模型保持不变。所谓“数据模型保持不变”,就是不能在类中增加、删除数据成员
2.隐藏实现细节;3.提高编译速度
QQAndQDTest.h
#pragma once
#include <QtWidgets/QWidget>
#include <QObject>
class QQAndQDTestPrivate;
class QQAndQDTest : public QObject
{
Q_OBJECT
public:
QQAndQDTest(QObject*parent = Q_NULLPTR);
~QQAndQDTest();
public:
void showMsg();
void setValue(int value);
int getValue();
private:
QQAndQDTestPrivate* const d_ptr;
Q_DECLARE_PRIVATE(QQAndQDTest)
};
class QQAndQDTestPrivate : public QObject
{
Q_OBJECT
public:
QQAndQDTestPrivate(QQAndQDTest* q, QObject* parent = Q_NULLPTR);
~QQAndQDTestPrivate();
void testFunc();
public:
QQAndQDTest* const q_ptr;
Q_DECLARE_PUBLIC(QQAndQDTest)
int m_value;
};
QQAndQDTest.cpp
#include "QQAndQDTest.h"
#include <QDebug>
QQAndQDTest::QQAndQDTest(QObject*parent)
: QObject(parent), d_ptr(new QQAndQDTestPrivate(this))
{
}
QQAndQDTest::~QQAndQDTest()
{
Q_D(QQAndQDTest);
delete d_ptr;
}
void QQAndQDTest::showMsg()
{
Q_D(QQAndQDTest);
qDebug() << d->m_value;
}
void QQAndQDTest::setValue(int value)
{
Q_D(QQAndQDTest);
d->m_value = value;
}
int QQAndQDTest::getValue()
{
Q_D(QQAndQDTest);
return d->m_value;
}
QQAndQDTestPrivate::QQAndQDTestPrivate(QQAndQDTest* q, QObject* parent)
: QObject(parent), q_ptr(q), m_value(0)
{
}
QQAndQDTestPrivate::~QQAndQDTestPrivate()
{
delete q_ptr;
}
void QQAndQDTestPrivate::testFunc()
{
Q_Q(QQAndQDTest);
q->showMsg();
}
main.cpp
#include "QQAndQDTest.h"
#include <QtWidgets/QApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QQAndQDTest t;
t.setValue(10);
t.showMsg();
return a.exec();
}
我们将值放在 主类的私有类中 ,通过d指针来访问,设置该值 和 获取该值