信号和槽是Qt应用开发的基础,它可是将两个毫无关系的对象连接在一起,槽和普通的C++函数是一样的,只是当它和信号连接在一起后,当发送信号的时候,槽会自动被调用只有加入了Q_OBJECT,你才能使用QT中的signal和slot机制。
所有QObject的派生类在官方文档中都推荐在头文件中放置宏Q_OBJECT,那么该宏到底为我们做了哪些工作?在qobjectdef.h中有下面的代码:
- #define Q_OBJECT \
- public: \
- Q_OBJECT_CHECK \
- static const QMetaObject staticMetaObject; \
- Q_OBJECT_GETSTATICMETAOBJECT \
- virtual const QMetaObject *metaObject() const; \
- virtual void *qt_metacast(const char *); \
- QT_TR_FUNCTIONS \
- virtual int qt_metacall(QMetaObject::Call, int, void **); \
- private:
首先定义了一个Q_OBJECT_CHECK宏,这个宏在Q_OBJECT宏的上方定义:
- #define Q_OBJECT_CHECK \
- template <typename T> inline void qt_check_for_QOBJECT_macro(const T &_q_argument) const \
- { int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument); i = i; }
Q_OBJECT_CHECK实现了一个模板函数,该函数调用了qYouForgotTheQ_OBJECT_Macro的函数,qYouForgotTheQ_OBJECT_Macro在宏Q_OBJECT_CHECK下面有定义:
- template <typename T>
- inline int qYouForgotTheQ_OBJECT_Macro(T, T) { return 0; }
- template <typename T1, typename T2>
- inline void qYouForgotTheQ_OBJECT_Macro(T1, T2) {}
从返回值情况上可以看到,调用的是有int返回值的那个模板函数。但是很不明白,为什么之后还要添加一句 i=i?,刨根之后,发现Q_OBJECT_CHECK宏并没有做什么工作。
然后Q_OBJECT又帮我们定义了一个静态的元对象,
- static const QMetaObject staticMetaObject; \
- Q_OBJECT_GETSTATICMETAOBJECT \
Q_OBJECT_GETSTATICMETAOBJECT宏从名字上看就是为了获取这个元对象,确实在定义了Q_NO_DATA_RELOCATION宏的情况下,Q_OBJECT_GETSTATICMETAOBJECT宏就为我们定义了获取静态元对象的方法。
- #ifdef Q_NO_DATA_RELOCATION
- #define Q_OBJECT_GETSTATICMETAOBJECT static const QMetaObject &getStaticMetaObject();
- #else
- #define Q_OBJECT_GETSTATICMETAOBJECT
- #endif
之后Q_OBJECT宏又给我们定义了连个虚函数用来获取元对象指针和设置源对象。
- virtual const QMetaObject *metaObject() const; \
- virtual void *qt_metacast(const char *); \
而定义的 QT_TR_FUNCTIONS 则表示是否支持I18N。
- #ifndef QT_NO_TRANSLATION
- # ifndef QT_NO_TEXTCODEC
- // full set of tr functions
- // ### Qt 5: merge overloads
- # define QT_TR_FUNCTIONS \
- static inline QString tr(const char *s, const char *c = 0) \
- { return staticMetaObject.tr(s, c); } \
- static inline QString trUtf8(const char *s, const char *c = 0) \
- { return staticMetaObject.trUtf8(s, c); } \
- static inline QString tr(const char *s, const char *c, int n) \
- { return staticMetaObject.tr(s, c, n); } \
- static inline QString trUtf8(const char *s, const char *c, int n) \
- { return staticMetaObject.trUtf8(s, c, n); }
- # else
- // no QTextCodec, no utf8
- // ### Qt 5: merge overloads
- # define QT_TR_FUNCTIONS \
- static inline QString tr(const char *s, const char *c = 0) \
- { return staticMetaObject.tr(s, c); } \
- static inline QString tr(const char *s, const char *c, int n) \
- { return staticMetaObject.tr(s, c, n); }
- # endif
- #else
- // inherit the ones from QObject
- # define QT_TR_FUNCTIONS
- #endif
只要有所实现,tr的方法就通过静态对象staticMetaObject的tr方法来实现。最后Q_OBJECT又定义了一个虚函数
- virtual int qt_metacall(QMetaObject::Call, int, void **);
看名字定义,应该是用来对元对象的调用。
合起来看所有的Q_OBJECT定义,都是为了操作元对象,并没有所谓的信号和槽,属性等内容,很显然,QObject对象能够支持这些功能,必然是通过QMetaObject这个元对象来实现的。尽管QMetaObject对象的实现有些庞大,但这个是所有的QOBject中最核心的一个实现,因此需要仔细分析该对象的每个定义:
- struct Q_CORE_EXPORT QMetaObject
- {
- const char *className() const; // 类名
- const QMetaObject *superClass() const; // 父类的元对象
- QObject *cast(QObject *obj) const; // 强制一个对象
- #ifndef QT_NO_TRANSLATION
- // ### Qt 4: Merge overloads
- QString tr(const char *s, const char *c) const; // 翻译函数
- QString trUtf8(const char *s, const char *c) const;
- QString tr(const char *s, const char *c, int n) const;
- QString trUtf8(const char *s, const char *c, int n) const;
- #endif // QT_NO_TRANSLATION
- int methodOffset() const; // 方法偏移量
- int enumeratorOffset() const; // 枚举偏移量
- int propertyOffset() const; // 属性偏移量
- int classInfoOffset() const; // 类信息数目
- int constructorCount() const; // 构造函数数目
- int methodCount() const; // 方法数目
- int enumeratorCount() const; // 枚举数据
- int propertyCount() const; // 属性数目
- int classInfoCount() const; // 类信息数目
- int indexOfConstructor(const char *constructor) const; // 构函函数索引
- int indexOfMethod(const char *method) const; // 方法索引
- int indexOfSignal(const char *signal) const; // 信号量索引
- int indexOfSlot(const char *slot) const; // 槽索引
- int indexOfEnumerator(const char *name) const; // 枚举索引
- int indexOfProperty(const char *name) const; // 属性索引
- int indexOfClassInfo(const char *name) const; // 类信息索引
- QMetaMethod constructor(int index) const; // 构造方法
- QMetaMethod method(int index) const; // 方法
- QMetaEnum enumerator(int index) const; // 枚举
- QMetaProperty property(int index) const; // 属性
- QMetaClassInfo classInfo(int index) const; // 类属性信息
- QMetaProperty userProperty() const; // 用户属性
- ///
- static bool checkConnectArgs(const char *signal, const char *method);
- static QByteArray normalizedSignature(const char *method);
- static QByteArray normalizedType(const char *type);
- // internal index-based connect
- static bool connect(const QObject *sender, int signal_index,
- const QObject *receiver, int method_index,
- int type = 0, int *types = 0);
- // internal index-based disconnect
- static bool disconnect(const QObject *sender, int signal_index,
- const QObject *receiver, int method_index);
- static bool disconnectOne(const QObject *sender, int signal_index,
- const QObject *receiver, int method_index);
- // internal slot-name based connect
- static void connectSlotsByName(QObject *o);
- // internal index-based signal activation
- static void activate(QObject *sender, int signal_index, void **argv); //obsolete
- static void activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv); //obsolete
- static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv);
- static void activate(QObject *sender, const QMetaObject *, int from_local_signal_index, int to_local_signal_index, void **argv); //obsolete
- // internal guarded pointers
- static void addGuard(QObject **ptr);
- static void removeGuard(QObject **ptr);
- static void changeGuard(QObject **ptr, QObject *o);
- static bool invokeMethod(QObject *obj, const char *member,
- Qt::ConnectionType,
- QGenericReturnArgument ret,
- QGenericArgument val0 = QGenericArgument(0),
- QGenericArgument val1 = QGenericArgument(),
- QGenericArgument val2 = QGenericArgument(),
- QGenericArgument val3 = QGenericArgument(),
- QGenericArgument val4 = QGenericArgument(),
- QGenericArgument val5 = QGenericArgument(),
- QGenericArgument val6 = QGenericArgument(),
- QGenericArgument val7 = QGenericArgument(),
- QGenericArgument val8 = QGenericArgument(),
- QGenericArgument val9 = QGenericArgument());
- static inline bool invokeMethod(QObject *obj, const char *member,
- QGenericReturnArgument ret,
- QGenericArgument val0 = QGenericArgument(0),
- QGenericArgument val1 = QGenericArgument(),
- QGenericArgument val2 = QGenericArgument(),
- QGenericArgument val3 = QGenericArgument(),
- QGenericArgument val4 = QGenericArgument(),
- QGenericArgument val5 = QGenericArgument(),
- QGenericArgument val6 = QGenericArgument(),
- QGenericArgument val7 = QGenericArgument(),
- QGenericArgument val8 = QGenericArgument(),
- QGenericArgument val9 = QGenericArgument())
- {
- return invokeMethod(obj, member, Qt::AutoConnection, ret, val0, val1, val2, val3,
- val4, val5, val6, val7, val8, val9);
- }
- static inline bool invokeMethod(QObject *obj, const char *member,
- Qt::ConnectionType type,
- QGenericArgument val0 = QGenericArgument(0),
- QGenericArgument val1 = QGenericArgument(),
- QGenericArgument val2 = QGenericArgument(),
- QGenericArgument val3 = QGenericArgument(),
- QGenericArgument val4 = QGenericArgument(),
- QGenericArgument val5 = QGenericArgument(),
- QGenericArgument val6 = QGenericArgument(),
- QGenericArgument val7 = QGenericArgument(),
- QGenericArgument val8 = QGenericArgument(),
- QGenericArgument val9 = QGenericArgument())
- {
- return invokeMethod(obj, member, type, QGenericReturnArgument(), val0, val1, val2,
- val3, val4, val5, val6, val7, val8, val9);
- }
- static inline bool invokeMethod(QObject *obj, const char *member,
- QGenericArgument val0 = QGenericArgument(0),
- QGenericArgument val1 = QGenericArgument(),
- QGenericArgument val2 = QGenericArgument(),
- QGenericArgument val3 = QGenericArgument(),
- QGenericArgument val4 = QGenericArgument(),
- QGenericArgument val5 = QGenericArgument(),
- QGenericArgument val6 = QGenericArgument(),
- QGenericArgument val7 = QGenericArgument(),
- QGenericArgument val8 = QGenericArgument(),
- QGenericArgument val9 = QGenericArgument())
- {
- return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0,
- val1, val2, val3, val4, val5, val6, val7, val8, val9);
- }
- QObject *newInstance(QGenericArgument val0 = QGenericArgument(0),
- QGenericArgument val1 = QGenericArgument(),
- QGenericArgument val2 = QGenericArgument(),
- QGenericArgument val3 = QGenericArgument(),
- QGenericArgument val4 = QGenericArgument(),
- QGenericArgument val5 = QGenericArgument(),
- QGenericArgument val6 = QGenericArgument(),
- QGenericArgument val7 = QGenericArgument(),
- QGenericArgument val8 = QGenericArgument(),
- QGenericArgument val9 = QGenericArgument()) const;
- enum Call {
- InvokeMetaMethod,
- ReadProperty,
- WriteProperty,
- ResetProperty,
- QueryPropertyDesignable,
- QueryPropertyScriptable,
- QueryPropertyStored,
- QueryPropertyEditable,
- QueryPropertyUser,
- CreateInstance
- };
- int static_metacall(Call, int, void **) const;
- static int metacall(QObject *, Call, int, void **);
- #ifdef QT3_SUPPORT
- QT3_SUPPORT const char *superClassName() const;
- #endif
- struct { // private data
- const QMetaObject *superdata; // 父类
- const char *stringdata; // 类名
- const uint *data; // 任意指向数据的指针
- const void *extradata; // 扩展数据
- } d;
- };
QMetaObject就内部一个结构体对象,包含了四个部分,分别是父类对象,自己元对象的名称,以及一个指针任意值的指针数据和扩展数据,一般情况下,d.data表示的是QMetaObjectPrivate对象指针,在priv函数中可以找到一些痕迹:
- static inline const QMetaObjectPrivate *priv(const uint* data)
- { return reinterpret_cast<const QMetaObjectPrivate*>(data); }
按照Qt的实现惯例,使用Private对象做一些具体的工作,于是就有了QMetaObjectPrivate和QObjectPrivate
- struct QMetaObjectPrivate // 注意是一个结构体
- {
- int revision; // 版本
- int className; // 类名,注意类型
- int classInfoCount, classInfoData; // 类信息数据和数量
- int methodCount, methodData; // 方法数据和数量
- int propertyCount, propertyData; // 属性数据和数量
- int enumeratorCount, enumeratorData; // 枚举数据和数量
- int constructorCount, constructorData; //since revision 2 // 构造函数数据和数量
- int flags; //since revision 3 // 标记
- int signalCount; //since revision 4 // 信号量数目
- // revision 5 introduces changes in normalized signatures, no new members
- // 从元数据中获取QMetaObjectPrivate对象指针,从data中得到!!
- static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
- { return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
- static int indexOfSignalRelative(const QMetaObject **baseObject,
- const char* name,
- bool normalizeStringData);
- static int indexOfSlot(const QMetaObject *m,
- const char *slot,
- bool normalizeStringData);
- static int originalClone(const QMetaObject *obj, int local_method_index);
- #ifndef QT_NO_QOBJECT
- //defined in qobject.cpp
- enum DisconnectType { DisconnectAll, DisconnectOne };
- static bool connect(const QObject *sender, int signal_index,
- const QObject *receiver, int method_index,
- int type = 0, int *types = 0);
- static bool disconnect(const QObject *sender, int signal_index,
- const QObject *receiver, int method_index,
- DisconnectType = DisconnectAll);
- static inline bool disconnectHelper(QObjectPrivate::Connection *c,
- const QObject *receiver, int method_index,
- QMutex *senderMutex, DisconnectType);
- #endif
- };
==================================================================
- class Q_CORE_EXPORT QObjectPrivate : public QObjectData
- {
- Q_DECLARE_PUBLIC(QObject)
- public:
- struct ExtraData // 定义额外数据
- {
- ExtraData() {}
- #ifndef QT_NO_USERDATA
- QVector<QObjectUserData *> userData;
- #endif
- QList<QByteArray> propertyNames; // 属性名列表
- QList<QVariant> propertyValues; // 属性值
- };
- struct Connection // 定义连接信息
- {
- QObject *sender; // 发送者
- QObject *receiver; // 接受者
- int method; // 方法
- uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
- QBasicAtomicPointer<int> argumentTypes; // 参数类型
- // The next pointer for the singly-linked ConnectionList
- Connection *nextConnectionList; // 下一个连接对象列表
- //senders linked list
- Connection *next; // 下一个连接
- Connection **prev; // 上一个连接
- ~Connection();
- };
- // ConnectionList is a singly-linked list
- struct ConnectionList { // 定义连接列表
- ConnectionList() : first(0), last(0) {}
- Connection *first; // 连接首
- Connection *last; // 连接尾
- };
- struct Sender // 定义发送者
- {
- QObject *sender; // 发送者
- int signal; // 信号
- int ref; // 引用计数
- };
- QObjectPrivate(int version = QObjectPrivateVersion);
- virtual ~QObjectPrivate();
- void deleteChildren(); // 删除所有子节点
- void setParent_helper(QObject *); // 设置父节点
- void moveToThread_helper(); // 转到某个线程中
- void setThreadData_helper(QThreadData *currentData, QThreadData *targetData); // 设置线程数据
- void _q_reregisterTimers(void *pointer); // 设置注册时间
- bool isSender(const QObject *receiver, const char *signal) const; // 判断信号量是否为发送者
- QObjectList receiverList(const char *signal) const; // 接受信号的对象列表
- QObjectList senderList() const; // 发出信息列表
- void addConnection(int signal, Connection *c); // 添加一个信号连接
- void cleanConnectionLists(); // 清理连接列表
- #ifdef QT3_SUPPORT
- void sendPendingChildInsertedEvents();
- void removePendingChildInsertedEvents(QObject *child);
- #endif
- static inline Sender *setCurrentSender(QObject *receiver,
- Sender *sender); // 设置当前发送者
- static inline void resetCurrentSender(QObject *receiver,
- Sender *currentSender,
- Sender *previousSender); // 重置当前发送者
- static int *setDeleteWatch(QObjectPrivate *d, int *newWatch); // 设置删除监听
- static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch); // 重置删除监听
- static void clearGuards(QObject *); // 清除管理者
- static QObjectPrivate *get(QObject *o) { // 从QObject对象中获取QObjectPrivate
- return o->d_func();
- }
- int signalIndex(const char *signalName) const; // 信号索引
- inline bool isSignalConnected(uint signalIdx) const; // 判断是否为信号连接
- public:
- QString objectName; // 对象名字
- ExtraData *extraData; // extra data set by the user // 额外数据
- QThreadData *threadData; // id of the thread that owns the object // 线程数据
- QObjectConnectionListVector *connectionLists; // 连接列表数组
- Connection *senders; // linked list of connections connected to this object // 发送者连接
- Sender *currentSender; // object currently activating the object // 当前发送者
- mutable quint32 connectedSignals[2]; // 连接信号
- #ifdef QT3_SUPPORT
- QList<QObject *> pendingChildInsertedEvents;
- #else
- // preserve binary compatibility with code compiled without Qt 3 support
- // keeping the binary layout stable helps the Qt Creator debugger
- void *unused; // 保留
- #endif
- QList<QPointer<QObject> > eventFilters;
- union {
- QObject *currentChildBeingDeleted; // 当前子节点被删除
- QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module
- };
- // these objects are all used to indicate that a QObject was deleted
- // plus QPointer, which keeps a separate list
- QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount; // 共享引用计数
- int *deleteWatch; // 删除监听者
- };
QObjectPrivate从QObjectData派生下来:
- class
- #if defined(__INTEL_COMPILER) && defined(Q_OS_WIN)
- Q_CORE_EXPORT
- #endif
- QObjectData {
- public:
- virtual ~QObjectData() = 0;
- QObject *q_ptr; // 当前指向的QOBject
- QObject *parent; // 指向的QObject父类
- QObjectList children; // 孩儿们
- uint isWidget : 1; // 是否为widget的标记
- uint pendTimer : 1; // 开启时钟
- uint blockSig : 1; // 阻塞信号标记
- uint wasDeleted : 1; // 是否参数标记
- uint ownObjectName : 1; // 是否含有对象名标记
- uint sendChildEvents : 1; // 发送到子对象时间标记
- uint receiveChildEvents : 1; // 接受子对象时间标记
- uint inEventHandler : 1; // 是否有事件句柄标记
- uint inThreadChangeEvent : 1; // 线程更改时间标记
- //是否有守护标记
- uint hasGuards : 1; //true iff there is one or more QPointer attached to this object
- uint unused : 22; // 保留
- int postedEvents; // 发送的数据
- QMetaObject *metaObject; // assert dynamic // 元对象
- };
QObjectData保留一些了基本的数据信息
- #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;
在元对象中获取类名和父类的方式很简单,直接即可。
- inline const char *QMetaObject::className() const
- { return d.stringdata; }
- inline const QMetaObject *QMetaObject::superClass() const
- { return d.superdata; }
元对象中cast函数的实现
- QObject *QMetaObject::cast(QObject *obj) const
- {
- if (obj) {
- const QMetaObject *m = obj->metaObject();
- do {
- if (m == this)
- return const_cast<QObject*>(obj);
- } while ((m = m->d.superdata));
- }
- return 0;
- }
如果对象obj存在,则对每一个obj的父类的源对象进行转换,如果是当前的元对象,则进行返回,否则返回0,也就是cast函数是在obj中查找当前元对象所在的QObject对象。