一、问题
学习Qt有一段时间了,信号槽用的也是666,可是对信号槽的机制还是一知半解,总觉着不是那么得劲儿,万一哪天面试被问到了还说不清楚,那岂不是很尴尬。最近抽空研究了下Qt的信号和槽进制,结果发现也不是那么难嘛!不管是同步还是异步,说白了都是函数回调,只是回调的地方变了而已
首先,我们先看如下几个问题,认真的思考下,从以前的知识储备中尝试回答他们,如果说这几个问题你都很清楚,那么恭喜你,你不适合看这篇文章。
moc预编译在干嘛
signals和slots关键字产生的理由
信号槽连接方式有什么区别
信号和槽函数有什么区别
connect到底干了什么
信号触发原理
下面我们就分模块来讲述下Qt的信号槽,首先分析下Moc他到底干了什么,如果没有他信号槽还能行吗?接着我们在来分析下最常用的connect函数,最后在看下信号执行后是怎么触发槽函数的?
二、Moc
qt中的moc 全称是 Meta-Object Compiler,也就是“元对象编译器”,当我们编译C++
文件时,如果类声明中包含了宏Q_OBJECT,则会生成另外一个C++源文件,也就是我们经常看到的moc_xxx.cpp文件,执行流程可能会像这样。
Q_OBJECT是一个非常重要的宏,他是Qt实现元编译系统的一个关键宏,这个宏展开后,里边包含了很多Qt帮助我们写的代码,包括了变量定义、函数声明等等,下边是一个测试例子,是我用moc命令生成的一个moc文件。
分析下面这个几个变量和函数,将有助于我们更好的理解元编译系统
1、变量
- static const qt_meta_stringdata_completerTst_t qt_meta_stringdata_completerTst:存储函数列表
- static const uint qt_meta_data_completerTst:类文件描述
2、Q_OBJECT展开后的函数声明
以下5个函数都是使用Q_OBJECT宏自动生成的
- void xxx::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
- const QMetaObject xxx::staticMetaObject
- const QMetaObject *xxx::metaObject()
- void *xxx::qt_metacast(const char *_clname)
- int xxx::qt_metacall(QMetaObject::Call _c, int _id, void **_a)