码迷,mamicode.com
首页 > Web开发 > 详细

Qt Meta Object system 学习

时间:2016-03-16 18:54:41      阅读:437      评论:0      收藏:0      [点我收藏+]

标签:

原文地址: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 };

 

Qt Meta Object system 学习

标签:

原文地址:http://www.cnblogs.com/lfsblack/p/5284602.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!