深入探究Connect函数(知识点整合)
来源:互联网 发布:国内旅游收入数据1978 编辑:程序博客网 时间:2024/06/04 18:25
connect,是QT中的连接函数,将信号发送者sender对象中的信号signal与接受者receiver中的member槽函数联系起来。
QObject::connect的定义是这样的:
static bool connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *member, Qt::ConnectionType =
#ifdef qdoc
Qt::AutoConnection
#else
#ifdef QT3_SUPPORT
Qt::AutoCompatConnection
#else
Qt::AutoConnection
#endif
#endif
);
inline bool connect(const QObject *sender, const char *signal,
const char *member, Qt::ConnectionType type =
#ifdef qdoc
Qt::AutoConnection
#else
#ifdef QT3_SUPPORT
Qt::AutoCompatConnection
#else
Qt::AutoConnection
#endif
#endif
) const;
其中第二个connect的实现其实只有一句话:
{ return connect(asender, asignal, this, amember, atype); }
所以对于connect函数的学习其实就是研究第一个connect函数。
在使用connect函数的时候一般是这样调用的:
两个宏:SIGNAL() 和SLOT();通过connect声明可以知道这两个宏最后倒是得到一个const char*类型。
在qobjectdefs.h中可以看到SIGNAL() 和SLOT()的宏定义:
这两个宏的作用就是把函数名转换为字符串并且在前面加上标识符。
比如:SIGNAL(read())展开后就是"2read()";同理SLOT(read())展开后就是"1read()"。
connect(sender,SIGNAL(signal()),receiver,SLOT(slot()));
实际上就是connect(sender,“2signal()”,receiver,“1slot())”;
在QObject.cpp文件中可以找到connect的实现代码,下面是去除了debug代码的connect实现。
判断连接是否已经建立:
- const void *cbdata[] = { sender, signal, receiver, method, &type };
- if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
- return true;
QInternal::ConnectCallback在qglobal.cpp中实现:
QInternal_CallBackTable 定义为(qglobal.cpp):
qInternalCallback定义为(qnamespace.h):
//这是一个函数指针 返回值是bool,只有一个参数为void**。这个指针在调用registerCallback加入列表。
判断signal是否合法
- if (!check_signal_macro(sender, signal, "connect", "bind"))
- return false;
在QObject.cpp文件中可以找到check_signal_macro的实现
extract的实现也在QObject中,它就是去字符串第一个字符,并且只取低2位的值。
这里有两个宏:QSIGNAL_CODE 和QSLOT_CODE。它们也是在qobjectdefs.h文件中定义的。这个定义与之前的SIGNAL和SLOT的定义是对应的。
获取signal的索引,其中metaObject()是在moc_name.cpp文件中生成的。
- const QMetaObject *smeta = sender->metaObject();
- const char *signal_arg = signal;
- ++signal; //skip code
- int signal_index = smeta->indexOfSignal(signal);
- if (signal_index < 0) {
- // check for normalized signatures
- tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
- signal = tmp_signal_name.constData() + 1;
- signal_index = smeta->indexOfSignal(signal);
- if (signal_index < 0) {
- err_method_notfound(sender, signal_arg, "connect");
- err_info_about_objects("connect", sender, receiver);
- return false;
- }
- }
return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
其中staticMetaObject也是在moc文件中定义的
- const QMetaObject MainWindow::staticMetaObject = {
- { &QMainWindow::staticMetaObject, qt_meta_stringdata_MainWindow,
- qt_meta_data_MainWindow, 0 }
- };
qt_meta_stringdata_MainWindow(具体名字和类名有关)就是staticconstchar[]类型。它记录了全部的signals和slots等的函数名、返回值和参数表的信息。
qt_meta_data_MainWindow(具体名字和类名有关)是staticconstuint[]类型。它记录了每一个函数的函数名、返回值和参数表在qt_meta_stringdata_MainWindow中的索引。同时它还记录了每一个函数的类型具体在qmetaobject.cpp文件中定义。
- enum MethodFlags {
- AccessPrivate = 0x00,
- AccessProtected = 0x01,
- AccessPublic = 0x02,
- AccessMask = 0x03, //mask
- MethodMethod = 0x00,
- MethodSignal = 0x04,
- MethodSlot = 0x08,
- MethodConstructor = 0x0c,
- MethodTypeMask = 0x0c,
- MethodCompatibility = 0x10,
- MethodCloned = 0x20,
- MethodScriptable = 0x40
- };
indexOfSignal(signal);的实现在qmetaobject.cpp中。其主要作用是利用qt_meta_stringdata_MainWindow 和qt_meta_data_MainWindow查找已经定义了的signal并返回索引。
- QByteArray tmp_method_name;
- int membcode = extract_code(method);
- if (!check_method_code(membcode, receiver, method, "connect"))
- return false;
- const char *method_arg = method;
- ++method; // skip code
- const QMetaObject *rmeta = receiver->metaObject();
- int method_index = -1;
- switch (membcode) {
- case QSLOT_CODE:
- method_index = rmeta->indexOfSlot(method);
- break;
- case QSIGNAL_CODE:
- method_index = rmeta->indexOfSignal(method);
- break;
- }
- if (method_index < 0) {
- // check for normalized methods
- tmp_method_name = QMetaObject::normalizedSignature(method);
- method = tmp_method_name.constData();
- switch (membcode) {
- case QSLOT_CODE:
- method_index = rmeta->indexOfSlot(method);
- break;
- case QSIGNAL_CODE:
- method_index = rmeta->indexOfSignal(method);
- break;
- }
- }
- if (method_index < 0) {
- err_method_notfound(receiver, method_arg, "connect");
- err_info_about_objects("connect", sender, receiver);
- return false;
- }
校验method并且查找它的索引。过程与signal类似。
- if (!QMetaObject::checkConnectArgs(signal, method)) {
- qWarning("QObject::connect: Incompatible sender/receiver arguments"
- "\n %s::%s --> %s::%s",
- sender->metaObject()->className(), signal,
- receiver->metaObject()->className(), method);
- return false;
- }
判断signal和method是否兼容,checkConnectArgs函数的在qmetaObject.cpp文件中实现。这个函数校验了signal和method的参数。当两者的参数一致或method参数比signal参数少(method与signal前几个参数一致)的时候返回true,其它返回false。
- int *types = 0;
- if ((type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
- && !(types = queuedConnectionTypes(smeta->method(signal_index).parameterTypes())))
- return false;
如果是以发消息的方式执行method就需要对参数类型进行判断。queuedConnectionTypes在QObject.cpp实现。实际上是在QMetatype.cpp中定义了一个
static conststruct { constchar * typeName;int type;} types[];在这里记录了全部类型和名称如({"void",QMetaType::Void});Void在Qmetatype.h中定义。
- QMetaObject::connect(sender, signal_index, receiver, method_index, type, types);
调用QMetaObject的connect函数,不详细写出。
- const_cast<QObject*>(sender)->connectNotify(signal - 1);
最后调用虚函数connectNotify表示connect已经执行完成。
- 深入探究Connect函数(知识点整合)
- 深入探究connect函数
- 深入探究connect函数
- 深入探究connect函数
- 深入探究connect函数
- 深入探究connect函数
- 深入探究connect函数
- 深入探究connect函数
- 深入探究connect函数
- 深入探究connect函数
- windows实验4-深入探究connect函数
- 深入探究CONNECT
- 微型技术博客004-深入探究connect函数
- 微型技术博客-探究connect()函数。
- 探究connect函数
- connect函数的探究
- qt中connect函数探究
- 深入探究内联函数
- windows 不能在本地启动 apache 2.4
- Jprofiler远程连接linux项目监控
- Codeforces Round #418 (Div. 2) B. An express train to reveries
- springboot集成dubbo,dubbox分布式服务框架
- VS 无法启动 IIS Express Web 服务器
- 深入探究Connect函数(知识点整合)
- 把数组排成最小的数
- STM32F40x/STM32F41x in-application programming using the USART中文版
- bzoj3110[Zjoi2013]K大数查询 主席树套线段树
- VS删除一行代码快捷键
- 三维重建方法--激光or视觉
- 机房个人重构之原型图、ER图(上)
- Ubuntu16.04中MySQL安装配置及修改字符集编码
- CEF关闭或者退出时报错崩溃问题原因