Qt Meta Object system 学习

原文地址:http://blog.csdn.net/ilvu999/article/details/8049908

使用 meta object system

  • 继承自 QOject
  • 类定义中添加 Q_OBJECT 宏
  • 使用 moc 程序对包含该宏的文件进行处理

采用 qmake 进行处理时,如果头文件xxx.h内包含 Q_OBJECT 宏,将生成 moc_xxx.cpp 文件。如果xxx.cpp文件内包含宏,将生成 xxx.moc 文件(这时,我们需要在xxx.cpp文件内添加 #include"xxx.moc")

Q_OBJECT宏

包括两个方面,

  • 该宏在C++中的展开,有编译预处理器完成
  • moc 程序对该宏的处理

宏定义

 1 #define Q_OBJECT  2 public:  3     Q_OBJECT_CHECK  4     static const QMetaObject staticMetaObject;  5     Q_OBJECT_GETSTATICMETAOBJECT  6     virtual const QMetaObject *metaObject() const;  7     virtual void *qt_metacast(const char *);  8     QT_TR_FUNCTIONS  9     virtual int qt_metacall(QMetaObject::Call, int, void **); 10 private: 11     Q_DECL_HIDDEN static const QMetaObjectExtraData staticMetaObjectExtraData; 12     Q_DECL_HIDDEN static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);

而宏 QT_TR_FUNCTIONS 将展开为我们使程序国际化经常使用的 tr 与 trUtf8函数

1 #  define QT_TR_FUNCTIONS 2     static inline QString tr(const char *s, const char *c = 0) 3         { return staticMetaObject.tr(s, c); } 4     static inline QString trUtf8(const char *s, const char *c = 0) 5         { return staticMetaObject.trUtf8(s, c); } 6     static inline QString tr(const char *s, const char *c, int n) 7         { return staticMetaObject.tr(s, c, n); } 8     static inline QString trUtf8(const char *s, const char *c, int n) 9         { return staticMetaObject.trUtf8(s, c, n); }

moc 处理

Q_OBJECT 为我们添加了这么多成员函数,而这些函数我们有没有自己去实现,那么其定义在哪儿呢? 这就是 moc 为我们做的,自动生成这些成员函数的定义,放于生成的 xxx.moc 或 moc_xxx.cpp 文件内

注意:两个文件的区别(如果你用cmake或其他工具的话,这点可能很重要)

  • 生成的 moc_xxx.cpp 中会自动包含 xxx.h 头文件,所以它可以被独立编译成目标文件(.o 或 .obj)
  • 生成的 xxx.moc 是不会包含 xxx.cpp 的(要是包含就出问题了,能发现吧?),因此 xxx.moc 中没有类定义,它无法被独立编译,只能被 include 到 xxx.cpp 中。

QMetaObject

既然 Q_OBJECT 展开成与 QMetaObject 有关的成员函数,看一下QMetaObject 都提供哪些常用功能

  • className() 返回类的名字
  • superClass() 返回父类的 QMetaObject 对象
  • method()与methodCount() 提供meta函数信息(包括signals, slots 与 invokable函数)
  • enumerator()与 enumeratorCount() 提供enum类型信息
  • propertyCount()与 property() 提供属性信息
  • constructor()与 constructorCount() 提供 meta-constructors 信息

既然meta object能为我们的类提供这么多信息,那么这些信息存放哪儿了(大家肯定都能猜到秘密在moc生成的文件内,但为清楚起见,我们看一下QMetaObject的定义)。

这是用 struct 定义的一个类,我们略过其它,只看其数据成员

  1 struct Q_CORE_EXPORT QMetaObject
  2 {
  3     const char *className() const;
  4     const QMetaObject *superClass() const;
  5
  6     QObject *cast(QObject *obj) const;
  7     const QObject *cast(const QObject *obj) const;
  8
  9 #ifndef QT_NO_TRANSLATION
 10     // ### Qt 4: Merge overloads
 11     QString tr(const char *s, const char *c) const;
 12     QString trUtf8(const char *s, const char *c) const;
 13     QString tr(const char *s, const char *c, int n) const;
 14     QString trUtf8(const char *s, const char *c, int n) const;
 15 #endif // QT_NO_TRANSLATION
 16
 17     int methodOffset() const;
 18     int enumeratorOffset() const;
 19     int propertyOffset() const;
 20     int classInfoOffset() const;
 21
 22     int constructorCount() const;
 23     int methodCount() const;
 24     int enumeratorCount() const;
 25     int propertyCount() const;
 26     int classInfoCount() const;
 27
 28     int indexOfConstructor(const char *constructor) const;
 29     int indexOfMethod(const char *method) const;
 30     int indexOfSignal(const char *signal) const;
 31     int indexOfSlot(const char *slot) const;
 32     int indexOfEnumerator(const char *name) const;
 33     int indexOfProperty(const char *name) const;
 34     int indexOfClassInfo(const char *name) const;
 35
 36     QMetaMethod constructor(int index) const;
 37     QMetaMethod method(int index) const;
 38     QMetaEnum enumerator(int index) const;
 39     QMetaProperty property(int index) const;
 40     QMetaClassInfo classInfo(int index) const;
 41     QMetaProperty userProperty() const;
 42
 43     static bool checkConnectArgs(const char *signal, const char *method);
 44     static QByteArray normalizedSignature(const char *method);
 45     static QByteArray normalizedType(const char *type);
 46
 47     // internal index-based connect
 48     static bool connect(const QObject *sender, int signal_index,
 49                         const QObject *receiver, int method_index,
 50                         int type = 0, int *types = 0);
 51     // internal index-based disconnect
 52     static bool disconnect(const QObject *sender, int signal_index,
 53                            const QObject *receiver, int method_index);
 54     static bool disconnectOne(const QObject *sender, int signal_index,
 55                               const QObject *receiver, int method_index);
 56     // internal slot-name based connect
 57     static void connectSlotsByName(QObject *o);
 58
 59     // internal index-based signal activation
 60     static void activate(QObject *sender, int signal_index, void **argv);  //obsolete
 61     static void activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv); //obsolete
 62     static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv);
 63     static void activate(QObject *sender, const QMetaObject *, int from_local_signal_index, int to_local_signal_index, void **argv); //obsolete
 64
 65     // internal guarded pointers
 66     static void addGuard(QObject **ptr);
 67     static void removeGuard(QObject **ptr);
 68     static void changeGuard(QObject **ptr, QObject *o);
 69
 70     static bool invokeMethod(QObject *obj, const char *member,
 71                              Qt::ConnectionType,
 72                              QGenericReturnArgument ret,
 73                              QGenericArgument val0 = QGenericArgument(0),
 74                              QGenericArgument val1 = QGenericArgument(),
 75                              QGenericArgument val2 = QGenericArgument(),
 76                              QGenericArgument val3 = QGenericArgument(),
 77                              QGenericArgument val4 = QGenericArgument(),
 78                              QGenericArgument val5 = QGenericArgument(),
 79                              QGenericArgument val6 = QGenericArgument(),
 80                              QGenericArgument val7 = QGenericArgument(),
 81                              QGenericArgument val8 = QGenericArgument(),
 82                              QGenericArgument val9 = QGenericArgument());
 83
 84     static inline bool invokeMethod(QObject *obj, const char *member,
 85                              QGenericReturnArgument ret,
 86                              QGenericArgument val0 = QGenericArgument(0),
 87                              QGenericArgument val1 = QGenericArgument(),
 88                              QGenericArgument val2 = QGenericArgument(),
 89                              QGenericArgument val3 = QGenericArgument(),
 90                              QGenericArgument val4 = QGenericArgument(),
 91                              QGenericArgument val5 = QGenericArgument(),
 92                              QGenericArgument val6 = QGenericArgument(),
 93                              QGenericArgument val7 = QGenericArgument(),
 94                              QGenericArgument val8 = QGenericArgument(),
 95                              QGenericArgument val9 = QGenericArgument())
 96     {
 97         return invokeMethod(obj, member, Qt::AutoConnection, ret, val0, val1, val2, val3,
 98                 val4, val5, val6, val7, val8, val9);
 99     }
100
101     static inline bool invokeMethod(QObject *obj, const char *member,
102                              Qt::ConnectionType type,
103                              QGenericArgument val0 = QGenericArgument(0),
104                              QGenericArgument val1 = QGenericArgument(),
105                              QGenericArgument val2 = QGenericArgument(),
106                              QGenericArgument val3 = QGenericArgument(),
107                              QGenericArgument val4 = QGenericArgument(),
108                              QGenericArgument val5 = QGenericArgument(),
109                              QGenericArgument val6 = QGenericArgument(),
110                              QGenericArgument val7 = QGenericArgument(),
111                              QGenericArgument val8 = QGenericArgument(),
112                              QGenericArgument val9 = QGenericArgument())
113     {
114         return invokeMethod(obj, member, type, QGenericReturnArgument(), val0, val1, val2,
115                                  val3, val4, val5, val6, val7, val8, val9);
116     }
117
118     static inline bool invokeMethod(QObject *obj, const char *member,
119                              QGenericArgument val0 = QGenericArgument(0),
120                              QGenericArgument val1 = QGenericArgument(),
121                              QGenericArgument val2 = QGenericArgument(),
122                              QGenericArgument val3 = QGenericArgument(),
123                              QGenericArgument val4 = QGenericArgument(),
124                              QGenericArgument val5 = QGenericArgument(),
125                              QGenericArgument val6 = QGenericArgument(),
126                              QGenericArgument val7 = QGenericArgument(),
127                              QGenericArgument val8 = QGenericArgument(),
128                              QGenericArgument val9 = QGenericArgument())
129     {
130         return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0,
131                 val1, val2, val3, val4, val5, val6, val7, val8, val9);
132     }
133
134     QObject *newInstance(QGenericArgument val0 = QGenericArgument(0),
135                          QGenericArgument val1 = QGenericArgument(),
136                          QGenericArgument val2 = QGenericArgument(),
137                          QGenericArgument val3 = QGenericArgument(),
138                          QGenericArgument val4 = QGenericArgument(),
139                          QGenericArgument val5 = QGenericArgument(),
140                          QGenericArgument val6 = QGenericArgument(),
141                          QGenericArgument val7 = QGenericArgument(),
142                          QGenericArgument val8 = QGenericArgument(),
143                          QGenericArgument val9 = QGenericArgument()) const;
144
145     enum Call {
146         InvokeMetaMethod,
147         ReadProperty,
148         WriteProperty,
149         ResetProperty,
150         QueryPropertyDesignable,
151         QueryPropertyScriptable,
152         QueryPropertyStored,
153         QueryPropertyEditable,
154         QueryPropertyUser,
155         CreateInstance
156     };
157
158     int static_metacall(Call, int, void **) const;
159     static int metacall(QObject *, Call, int, void **);
160
161 #ifdef QT3_SUPPORT
162     QT3_SUPPORT const char *superClassName() const;
163 #endif
164
165     struct { // private data
166         const QMetaObject *superdata;
167         const char *stringdata;
168         const uint *data;
169         const void *extradata;
170     } d;
171 };

其中呢,

  • uperdata,指向父类的MetaObject,容易理解
  • extradata 似乎目前未启用,不用理解
  • 剩下两个是什么呢? 如你所想,就在 moc 生成的文件内

moc生成的文件

随便找个 moc 文件出来看看

1 static const uint qt_meta_data_HPixmapScene[] = {...};
2 static const char qt_meta_stringdata_HPixmapScene[] = {...};
3 const QMetaObject HPixmapScene::staticMetaObject = {
4 { &QGraphicsScene::staticMetaObject, qt_meta_stringdata_HPixmapScene,
5 qt_meta_data_HPixmapScene, 0 }
6 }; 

这是一个QGraphicsScene的子类。对比前面QMetaObject的数据成员看看,是不是很简单:

  • 先分别定义1个 uint 和 char 的数组,
  • 用这两个数组首地址和父类的MetaObject的指针初始化 staticMetaObject
  • 这个 staticMetaObject 是我们自己的类的静态成员变量

uint数组
接下来我们可以看看 uint 数组,这个数组中存放的是一些索引值,来指导我们从char字符串中提取信息

 1 static const uint qt_meta_data_HPixmapScene[] = {
 2
 3 // content:
 4 4, // revision
 5 0, // classname
 6 0, 0, // classinfo
 7 2, 14, // methods
 8 0, 0, // properties
 9 0, 0, // enums/sets
10 0, 0, // constructors
11 0, // flags
12 0, // signalCount
13
14 // slots: signature, parameters, type, tag, flags
15 18, 14, 13, 13, 0x0a,
16 41, 37, 13, 13, 0x0a,
17
18 0 // eod
19 }; 

对比QMetaObject用到的数据结构 QMetaObjectPrivate,看看,是不是豁然开朗了:uint 数组中的第一段 就对应这个结构体

 1 struct QMetaObjectPrivate
 2 {
 3     int revision;
 4     int className;
 5     int classInfoCount, classInfoData;
 6     int methodCount, methodData;
 7     int propertyCount, propertyData;
 8     int enumeratorCount, enumeratorData;
 9     int constructorCount, constructorData; //since revision 2
10     int flags; //since revision 3
11     int signalCount; //since revision 4
12     // revision 5 introduces changes in normalized signatures, no new members
13     // revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself
14
15     static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
16     { return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
17
18     static int indexOfSignalRelative(const QMetaObject **baseObject,
19                                      const char* name,
20                                      bool normalizeStringData);
21     static int indexOfSlotRelative(const QMetaObject **m,
22                            const char *slot,
23                            bool normalizeStringData);
24     static int originalClone(const QMetaObject *obj, int local_method_index);
25
26 #ifndef QT_NO_QOBJECT
27     //defined in qobject.cpp
28     enum DisconnectType { DisconnectAll, DisconnectOne };
29     static void memberIndexes(const QObject *obj, const QMetaMethod &member,
30                               int *signalIndex, int *methodIndex);
31     static bool connect(const QObject *sender, int signal_index,
32                         const QObject *receiver, int method_index_relative,
33                         const QMetaObject *rmeta = 0,
34                         int type = 0, int *types = 0);
35     static bool disconnect(const QObject *sender, int signal_index,
36                            const QObject *receiver, int method_index,
37                            DisconnectType = DisconnectAll);
38     static inline bool disconnectHelper(QObjectPrivate::Connection *c,
39                                         const QObject *receiver, int method_index,
40                                         QMutex *senderMutex, DisconnectType);
41 #endif
42 };
时间: 2024-11-08 15:20:05

Qt Meta Object system 学习的相关文章

Qt Meta Object System-元对象系统

Qt Meta Object System-元对象系统 元对象系统的构成 QObject为所有需要利用元对象系统的对象提供一个基类. Q_OBJECT宏,在类的声明体内激活meta-object功能,比如动态属性.信号和槽. Meta Object Compiler(MOC),为每个QObject派生类生成代码,以支持meta-object功能. QObject定义了从一个QObject对象访问meta-object功能的接口,Q_OBJECT宏用来告诉编译器该类需要激活meta-object功

Qt Installer Framework的学习(三)

Qt Installer Framework的学习(三) Qt Installer Framework的样例中.通常是这种:config目录一般放了一个config.xml文件,包括的是安装配置xml的内容.packages包括的是须要安装的包的内容.普通情况不止一个安装包,每个安装包也不止是一个文件,那么每个包都有目录,里面的目录中有data以及meta子目录. data目录中是安装包的内容,meta目录中是package.xml文件.这个文件包括的是安装包的安装配置内容.另一些项目包括的是p

Qt Installer Framework的学习(二)

Qt Installer Framework的学习(二) Qt Installer Framework的一些操作可以使用最常见的Qt项目来表示,也就是说,书写pro文件,使用qmake运行之,除了能够编译正常的项目之外,也可以为项目打包.这里最重要的就是binarycreator了.下面就是我命令行使用binarycreator的时候弹出的一些提示,我们可以根据这样的提示,来了解究竟有哪些使用的方法. 上海萌梦信息科技有限公司(微博:http://weibo.com/qtdream)原创文章,首

Java Object类学习笔记

看下Api文档的一些说明 public class Object Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class. Since: JDK1.0 从JDK1.0就已经存在的元老类,类结构的根,所有类的父类,所有类都实现了这个类的方法,包含

QML官方教程——Using the Qt Quick Particle System

附网址:http://qt-project.org/doc/qt-5/qtquick-effects-particles.html Using the Qt Quick Particle System-- 使用Qt Quick粒子系统 所有粒子系统的类型都可以在QtQuick.Particles模块文档中找到. 注意想要使用粒子模块中的类型,你需要使用下面这个代码进行引入: import QtQuick.Particles 2.0 · The ParticleSystem 粒子系统包含4个主要的

Object C学习笔记25-文件管理(一)

在此篇文章中简单记录一下文件管理,在Object C中NSFileManager用于管理文件已经路径.在Object C中的文件路径可以是相对路径也可以是绝对路径.斜线"/"开头,斜线实际上就是一个目录,称为 根目录.字符(-)用作用户主目录的缩写.点" . "表示当前目录,两点"  .. "表示父目录. 一. 创建NSFileManager 对象 NSFileManager非常简单,可以使用如下方式来创建NSFileManager对象. NSS

Object C学习笔记26-文件管理(二)

上一篇简单的介绍了如何获取文件属性,删除,拷贝文件等,本文继续记录Object C中文件IO操作. 一. 获取文件的执行主目录 在Object C中提供了一个方法 NSHomeDirectory() 用于获得执行执行的主目录,使用如下代码测试: NSString *homePath=NSHomeDirectory(); NSLog(@"执行文件的主目录:%@",homePath); 通过以上代码可以正确的输出应用程序的执行目录,上一张也提到了文件的目录问题,这个和Windows系统的有

Object C学习初步

最近乘着项目不太紧张的时候,赶紧给自己冲了一下电.其实我自己最熟悉的平台应该是.net,所以当初上手windows phone的话是很快,我记得当初是一边跟着项目进展,一边自己开始学习前台的XAML语言以及页面的布局,所以一个项目跟下来的话windows phone平台也就差不多了. 早先就有过学习ios的想法,应该iphone实在是太酷了,感觉开发ios比windows phone更加有成就感.但是前前后后一直在往后推迟,因为ios的同事们一直给我灌输的思想就是oc语言还有挺难学的,相比较c#

Qt下UDP编程学习

一.概述: #include <QUdpSocket> QUdpSocket类继承自QAbstractSocket,该类中的所有函数都是可重入的(reentrent). 二.介绍: QUdpSocket公有类型: enum BindFlag {ShareAddress, DontShareAddress, ReuseAddressHint, DefaultForPlatform } flags BindMode QUdpSocket公共函数: QUdpSocket ( QObject * pa