d指针是在主类中使用的,来获取私有子类成员指针
q指针是在私有数据类中使用的,来获取主类对象指针
D-指针
私有成员总是不可见的,Qt中私有成员不仅仅是简单封装一下,将访问权限改为private,它将所有私有数据封装在私有类里(命名就是 classname##private), 这样一来连用户都不知道他到底封装了什么,程序中只有这个私有类成员指针,这个指针就是D-指针。
从QObject开始看
[c-sharp]
1. class QObject
2. {
3. Q_DECLARE_PRIVATE(QObject)
4. public:
5. Q_INVOKABLE explicit QObject(QObject *parent=0);
6. protected:
7. QObject(QObjectPrivate &dd, QObject *parent = 0);
8. QScopedPointer<QObjectData> d_ptr;
9. // others
10.}
展开后
[c-sharp]
1. class QObject
2. {
3. inline QObjectPrivate* d_func() { return reinterpret_cast(qGetPtrHelper(d_ptr)); }
4. inline const QObjectPrivate* d_func() const { return reinterpret_cast(qGetPtrHelper(d_ptr)); }
5. friend class QObjectPrivate;
6. public:
7. Q_INVOKABLE explicit QObject(QObject *parent=0);
8. protected:
9. QObject(QObjectPrivate &dd, QObject *parent = 0);
10.QScopedPointer<QObjectData> d_ptr;
11.// others
12.}
QObject的构造函数如下:
[c-sharp]
1. QObject::QObject(QObject *parent)
2. : d_ptr(new QObjectPrivate)
3. {
4. // others
5. }
6. QObject::QObject(QObjectPrivate &dd, QObject *parent)
7. : d_ptr(&dd)
8. {
9. // others
10.}
也就是QObjectData *d_ptr = new QObjectPrivate
显然QObjectPrivate 继承了 QObjectData ;
如下
[c-sharp]
1. QObjectData {
2. public:
3. virtual ~QObjectData() = 0;
4. // others
5. };
[c-sharp]
1. class Q_CORE_EXPORT QObjectPrivate : public QObjectData
2. {
3. Q_DECLARE_PUBLIC(QObject)
4. public:
5. QObjectPrivate(int version = QObjectPrivateVersion);
6. virtual ~QObjectPrivate();
7. // others
8. }
看看QObject的一个方法
[c-sh
1. QString QObject::objectName() const
2. {
3. Q_D(const QObject);
4. return d->objectName;
5. }
展开后
[c-sharp]
1. QString QObject::objectName() const
2. {
3. QObjectPrivate * const d = d_func()
4. return d->objectName;
5. }
所以Qt 为我们把从 d_func() 获取 QObjectPrivate 指针的代码给封装起来了,之后就可以直接使用d->
QObject的第二个构造函数使用传入的 QObjectPrivate 对象,但它是 protected 的,也就是说,你不能在外部类中使用这个构造函数。那么这个构造函数有什么用呢?我们来看一下 QWidget 的代码:
[c-]
1. class: public QObject, public QPaintDevice
2. {
3. Q_OBJECT
4. Q_DECLARE_PRIVATE(QWidget)
5. // others
6. }
QWidget 是 QObject 的子类,然后看它的构造函数:
1. QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
2. : QObject(dd, 0), QPaintDevice()
3. {
4. Q_D(QWidget);
5. QT_TRY {
6. d->init(parent, f);
7. } QT_CATCH(...) {
8. QWidgetExceptionCleaner::cleanup(this, d_func());
9. QT_RETHROW;
10.}
11.}
显然了QWidgetPrivate 继承了QObjectPrivate
于是我们已经明白,为什么 QWidget 中找不到 d_ptr 了,因为所有的 d_ptr 都已经在父类 QObject 中定义好了!尝试展开一下 Q_DECLARE_PRIVATE 宏,你就能够发现,它实际上把父类的 QObjectPrivate 指针偷偷地转换成了 QWidgetPrivate 的指针。
因此有如下结论:
1、在基类中定义一个protected权限的基类私有类d_ptr指针;
2、在每个派生类中用本类私有类初始化d_ptr(该私有类需要继承基类私有类),并定义d_func(),获取基类d_ptr,这个d_func()是由 Q_DECLARE_PRIVATE展开得来的,并将其转换为当前私有类指针;
3、在函数中使用Q_D,这样就可以使用d了;
4、在私有数据继承体系中,不要忘记将析构函数定义为虚函数,基类析构函数中释放d_ptr,以防内存泄露!!!
============================================================
Q-指针
q指针是在私有数据类中使用的,来获取主类指针。
[cpp]
1. class Q_CORE_EXPORT QObjectPrivate : public QObjectData
2. {
3. Q_DECLARE_PUBLIC(QObject)
4. public:
5. //others...
6. };
展开后:
[cpp]
1. class Q_CORE_EXPORT QObjectPrivate : public QObjectData
2. {
3. inline QObject* q_func() { returnstatic_cast<QObject *>(q_ptr); } /
4. inlineconst QObject* q_func() const { returnstatic_cast<const QObject *>(q_ptr); } /
5. friendclass QObject;
6. //others
7. }
QObjectData定义如下:
[cpp]
1. QObjectData {
2. public:
3. QObject *q_ptr;
4. //others
5. }
6. #define Q_Q(QObject) QObject * const q = q_func()
三、使用的例子:
在使用调色板中
[cpp]
1. void QWidget::setPalette(const QPalette &palette)
2. {
3. Q_D(QWidget); //得到私有成员 QWidgetPrivate指针 d
4. setAttribute(Qt::WA_SetPalette, palette.resolve() != 0);
5. QPalette naturalPalette = d->naturalWidgetPalette(d->inheritedPaletteResolveMask);
6. QPalette resolvedPalette = palette.resolve(naturalPalette);
7. d->setPalette_helper(resolvedPalette); //调用QWidgetPrivate::setPalette_helper()
8. }
9. void QWidgetPrivate::setPalette_helper(const QPalette &palette)
10.{
11.Q_Q(QWidget);
12.if (data.pal == palette && data.pal.resolve() == palette.resolve())
13.return;
14.data.pal = palette;
15.updateSystemBackground();
16.propagatePaletteChange();
17.updateIsOpaque();
18.q->update(); //调用QWidget::update()
19.updateIsOpaque();
20.}
#define Q_DECLARE_PRIVATE(Class) \ #define Q_DECLARE_PRIVATE_D(Dptr, Class) \ #define Q_DECLARE_PUBLIC(Class) \ #define Q_D(Class) Class##Private * const d = d_func() |
相关推荐
为了⽀持这样的⽤法,shared_ptr提供了类似的转型函数 static_pointer_cast<T>()、const_pointer_cast<T>()、dynamic_pointer_cast<T>(),它们与标准的转型操作符static_cast<T>()、const_cast<T>()和dynamic_cast<T...
lParam --值<br>#define GM_SET_ROW_MODIFY WM_GRID_USER_OUTER + 43<br><br>//得到单元修改标志:wParam -- GridCell_T指针<br>//退出编辑之后该标志是无效的<br>//可以在GN_EXIT_CELL_EDITBOX通知中获得该标志...
58<br><br>0081 文本中首字母改为大写 59<br><br>0082 C#随机数的产生 59<br><br>0083 身份证从15位升至18位算法 60<br><br>0084 十进制数转二进制数的算法 60<br><br>0085 十进制数转八进制数的算法 61...
//链接指针<br>int reach_time;//到达时间<br>int left_time;//估计运行时间<br>int run_time;//已运行时间<br>char status;//R就绪 c完成<br>PCB();<br>PCB(char aname,int areach_time,int aleft_time,int arun_...
07_31_C_01_指针和指针赋值&外挂原理07_31_C_01_指针和指针赋值&外挂原理07_31_C_01_指针和指针赋值&外挂原理07_31_C_01_指针和指针赋值&外挂原理07_31_C_01_指针和指针赋值&外挂原理07_31_C_01_指针和指针赋值&外挂...
PDF格式<br>让你不再害怕指针<br><br>前言:复杂类型说明<br>1、细说指针<br> 1.指针的类型<br> 2.指针所指向的类型<br> 3.指针的值----或者叫指针所指向的内存区或地址<br> 4指针本身所占据的内存区<br>2、指针的...
BOOKMARK.ZIP <br>BOOKMARK控件(20KB)<END><br>18,AresButtonPro.ZIP <br>任意形状立体动态按钮(306KB)<END><br>19,SysTray.ZIP <br>托盘控件(9KB)<END> <br>20,Recorder.ZIP <br>录音控件(15KB)<END><br>21,...
08_01_C_02_二级指针&函数指针08_01_C_02_二级指针&函数指针08_01_C_02_二级指针&函数指针08_01_C_02_二级指针&函数指针08_01_C_02_二级指针&函数指针08_01_C_02_二级指针&函数指针08_01_C_02_二级指针&函数指针08_...
<br>内容及步骤:<br>1、 在前一个实验的基础上,继续增加搜索函数Search(int Info)(如果找到结点,返回指向该结点的指针,如果没有,则返回空指针)和删除函数bool Delete(int Info),如果找到结点,则删除该结点,并...
<br> }<br> 获取剪贴板信息并且朗读:<br> void ReadClipText()<br> {<br> if( g_bAgentOK)<br> { <br> // 只有文本文件才朗读<br> if( IsClipboardFormatAvailable(CF_TEXT))<br> {<br> if (OpenClipboard(g_...
<br>第三部分 数值计算与趣味数学篇<br> <br>075 绘制余弦曲线和直线的迭加<br>076 计算高次方数的尾数 <br>077 打鱼还是晒网 <br>078 怎样存钱以获取最大利息 <br>079 阿姆斯特朗数 <br>080 亲密数 <br>081 自守数 ...
【说明】 一下规则为我们学校要求的 各个具体题目不一样 根据需要进行修改<br><br>...否找到s,返回<br>入口指针<br>int to10(char s[],int n)<br> 输入:数字字符串s,s的进制数n<br> 输出:由s转化成的十进制数<br>
看好在下:<br>第一章 CGI <br>第二章 ACTIVEX<br>第三章:异常处理<br>第四章 多线程/多进程<br>……<br>……<br>1.1 如何编写CGI程序<br><br>CGI的工作原理介绍:CGI(Common Gateway Interface)是一个WEB服务器...
<类型> const * <指针变量> 或 const <类型> * <指针变量> 2、常量指针: <类型> * const <指针变量> 3、指向常量的常量指针: <类型> const * const <指针变量> 或 const <类型> * const <指针变量>
base 待排序的数组,melem 数组的元素个数,width 每个元素的大小,<br> fcmp 用于对数组元素进行比较的函数指针,该函数由自己另外编写,有2个参数.<br><br>所属文件: <stdlib.h><br><br><br>
<br><br><br><br>(图一)<br><br>根据上篇文章内容,该图该可以等价于如下的二维表格表示:<br><br><br><br>(图二)<br><br>而对应于该表格的是一个ColumnFirstDynamicArray,共有10个结点,每个结点的取值如下表...
这个文件提供了若干个类和模板类,开发者只需关注其中两个模板类:CDHtmlDialogImpl<>和CMultiPageDHtmlDialogImpl<>,第一个模板类实现了WEB页面布局的对话框,第二个模板类以第一个类为基础,扩展成了在一个对话框...
图 365<br>12.1 基本概念 365<br>12.2 应用 366<br>12.3 特性 368<br>12.4 抽象数据类型Graph和Digraph 370<br>12.5 无向图和有向图的描述 371<br>12.5.1 邻接矩阵 371<br>12.5.2 邻接压缩表 373<br>12.5.3 邻接链表...
08_07_C_04_结构体指针08_07_C_04_结构体指针08_07_C_04_结构体指针08_07_C_04_结构体指针08_07_C_04_结构体指针08_07_C_04_结构体指针08_07_C_04_结构体指针08_07_C_04_结构体指针08_07_C_04_结构体指针08_07_C_04_...
智能指针 智能指针shared_ptr的初始化 的初始化 shared_ptr是智能指针,是模板,头⽂件是memory: shared_ptr<string> p1 最安全的使⽤⽅法是调⽤make_shared标准库函数,此函数在动态内存中分配⼀个对象并初始化它...