Qt d指针q指针
程序员文章站
2024-02-29 18:27:40
...
文章目录
Qt d指针q指针
概述
如果程序从一个以前版本的库动态链接到新版本的库之后,能够继续正常运行,而不需要重新编译,那么我们就说这个库是二进制兼容的。如果一个程序需要重新编译来运行一个新版本的库,但是不需要对程序的源代码进一步的修改,这个库就是源代码兼容的。
Q_DECLARE_PRIVATE和Q_DECLARE_PUBLIC
template <typename T> static inline T *qGetPtrHelper(T *ptr) { return ptr; }
template <typename Wrapper> static inline typename Wrapper::pointer qGetPtrHelper(const Wrapper &p) { return p.data(); }
宏Q_DECLARE_PRIVATE
定义
#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;
它实际上创建了两个 inline 的d_func()
函数,返回值分别是我们的d_ptr
指针和const
指针,又把ClassPrivate
声明为Class
的友元,使得ClassPrivate
可以访问Class
中的私有成员。
宏Q_DECLARE_PUBLIC
定义
#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;
与之前的宏相对,返回的是指向class的指针,因为我们可能在ClassPrivate的实现里访问Class的一些东西。让主类通过d_func()访问ClassPrivate的数据,反过来让ClassPrivate访问主类的数据用的就是q_func()
Q_Q和Q_D
以下两个宏对指针访问进行了简化,以后代码中使用d和q就可以了。
#define Q_D(Class) Class##Private * const d = d_func()
#define Q_Q(Class) Class * const q = q_func()
不能把ClassPrivate
的头文件和Class
头文件放到一起,常见做法是:定义一个ClassPrivate的头文件,例如使用myclass_p.h
(这也是Qt的命名方式)。并且记住,不要把myclass_p.h放到发布的include
下面!在myclass.h
中,使用前向声明Class MyClassPrivate
。
d指针的优点
- 隐藏实现细节
- 头文件中没有任何实现细节,可以作为API使用。
- 由于原本在头文件的实现部分转移到了源文件,所以编译速度有所提高。
- 实现二进制兼容性,避免重新编译
应用实例
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class WidgetPrivate;
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
QString getText() const;
void setText(const QString &value);
void test();
protected:
//使用智能指针无需在析构函数中释放
QScopedPointer<WidgetPrivate> d_ptr;
private:
QString text;
Q_DECLARE_PRIVATE(Widget)
Q_DISABLE_COPY(Widget)
};
#endif // WIDGET_H
widgetprivate_p.h
#ifndef WIDGETPRIVATE_H
#define WIDGETPRIVATE_H
#include <QDebug>
#include <QScopedPointer>
class Widget;
class WidgetPrivate
{
Q_DISABLE_COPY(WidgetPrivate)
Q_DECLARE_PUBLIC(Widget)
public:
WidgetPrivate(Widget *q);
~WidgetPrivate();
Widget *const q_ptr;
void init();
void setWidgetText(QString text);
};
#endif // WIDGETPRIVATE_H
widget.cpp
#include "widget.h"
#include "widgetprivate_p.h"
WidgetPrivate::WidgetPrivate(Widget *q):q_ptr(q)
{
}
WidgetPrivate::~WidgetPrivate()
{
}
void WidgetPrivate::init()
{
qDebug() << "get WidgetPrivate!";
}
void WidgetPrivate::setWidgetText(QString text)
{
Q_Q(Widget);
q->setText(text);
}
Widget::Widget(QWidget *parent)
: QWidget(parent),d_ptr(new WidgetPrivate(this))
{
//该方法获取d指针,Q_D是对它的封装
d_func()->init();
}
Widget::~Widget()
{
}
void Widget::test()
{
Q_D(Widget);
//为了展示q指针的使用,在私有数据中调用主类的setText方法
d->setWidgetText("set by WidgetPrivate!");
qDebug() << getText();
}
QString Widget::getText() const
{
return text;
}
void Widget::setText(const QString &value)
{
text = value;
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.test();
w.show();
return a.exec();
}
上一篇: 计算机的存储规则(反码补码浮点编码)