版权声明
请尊重原创作品。转载请保持文章完整性,并以超链接形式注明原始作者“tingsking18”和主站点地址,方便其他朋友提问和指正。
QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数
QT源码解析(二)深入剖析QT元对象系统和信号槽机制
QT的信号和槽机制是用来在对象间通讯的方法,当一个特定事件发生的时候,signal会被 emit 出来,slot 调用是用来响应相应的 signal 的。简单点说就是如何在一个类的一个函数中触发另一个类的另一个函数调用,而且还要把相关的参数传递过去.好像这和回调函数也有点关系,但是消息机制可比回调函数有用多了,也复杂多了。
下面的代码是我写的一个继承QLabel的类,是QLabel可以响应鼠标单击的消息。
这段代码很简单,讲述了QT的singal和slot的使用。下面我们就深入QT的源码内部,来看一看QT是如何实现singal和slots的。
#include “main.moc” 的意思就是使编译器找到moc对Q_OBJECT处理后的标准C++文件。编译的时候我们需要首先在该目录中使用 qmake -project 生成一个 .pro 文件,该文件含有工程细节,然后使用 qmake 产生 Makefile,最后 nmake 就可以产生可执行文件了。我们看看在nmake之后除了生成目标代码和可执行文件之外,还有一个main.moc文件,这个文件是moc产生的一个中间文件。
现在我们要看一下Q_OBJECT宏到底是什么?他与main.moc有什么关联呢?相信我介绍完了Q_OBJECT宏之后,再看main.moc就能明白其所有函数的含义了。我们先到objectdefs.h 文件中看一下Q_OBJECT宏的定义:
#define Q_OBJECT /
public: /
Q_OBJECT_CHECK /
static const QMetaObject staticMetaObject; /
virtual const QMetaObject *metaObject() const; /
virtual void *qt_metacast(const char *); /
QT_TR_FUNCTIONS /
virtual int qt_metacall(QMetaObject::Call, int, void **); /
private:
1首先调用了 Q_OBJECT_CHECK (插入了一个 qt_check_for_QOBJECT_macro 的 template function)
2 然后是全局常量 QMetaObject 对象,因此可以用 QClassname::staticMetaObject 直接访问,另外提供了两个接口函数 metaObject() 用于不同的 class 返回自己的 staticMetaObject、qt_metacast() 用于转换,我们在 moc 产生的文件里面可以找到这两个接口的实现:
const QMetaObject *ClickedLabel::metaObject() const
{
return &staticMetaObject;
}
void *ClickedLabel::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_ClickedLabel))
return static_cast<void*>(const_cast< ClickedLabel*>(this));
return QLabel::qt_metacast(_clname);
}
3 宏QT_TR_FUNCTIONS是和i18n相关的,我们暂时不用去管它。
# define QT_TR_FUNCTIONS /
static inline QString tr(const char *s, const char *c = 0) /
{ return staticMetaObject.tr(s, c); }
4 最后是接口函数qt_metacall,他的作用是查表,调用函数
int ClickedLabel::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QLabel::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {