关于Qt信号与槽机制的传递方向性研究(结论其实是错误的,但是可以看看分析过程)
最近由于项目的需求,一直在研究Qt。信号与槽机制是Qt的一大特色,该机制允许两者间传递参数,依次来实现对象间的通信。这个参数会分别存在于信号的参数列表和槽函数的参数列表中。需要注意的是,若将槽函数绑定至信号,槽函数的参数列表元素数目只能少于等于信号的参数列表元素数目。而且顺序和类型不能改变。至于缺少的参数应从信号参数尾部开始缺少。
突然今天想起来一个问题,如果一个对象发出信号,将内部的一个成员变量(非简单类型)作为参数向外发送,槽函数就可以接收到这个对象,那么槽函数是否可以完全操作这个对象呢?如果可以完全操作,那么这个信号与槽机制就是一个双向的通讯过程,即A可以触发B,B又能对A进行操作;如果操作无效,则说明该机制是一个单向的通讯过程,即A触发B,B进行处理,但不能反向写数据。
闲言少叙,让实例说话
先建立一个console application
建立头文件CustomClasses.h
代码如下:
- #ifndef CUSTOMCLASSES_H
- #define CUSTOMCLASSES_H
- #include <QObject>
- class TPerson
- {
- private:
- QString _Name;
- public:
- TPerson();
- void SetName(QString Name);
- QString GetName();
- };
- class TSender:public QObject
- {
- Q_OBJECT
- private:
- TPerson _p;
- public:
- TSender();
- void click();
- void disp();
- signals:
- void NewName(TPerson P);
- };
- class TReceiver:public QObject
- {
- Q_OBJECT
- public:
- TReceiver();
- public slots:
- void GetNewName(TPerson P);
- };
- #endif // CUSTOMCLASSES_H
这里定义了三个类TPerson、TSender和TReceiver。
TPerson是一个很简单的类,包含了一个私有成员_Name,分别具有Get和Set方法。
TSender类中包含一个私有的TPerson实例_p,click()方法模拟按钮单击,当执行click()方法后会发出NewName(TPerson P)信号。
TReceiver类中包含一个GetNewName(TPerson P)槽,用于接收来自TSender的NewName(TPerson P)信号。
建立对应的CustomClasses.cpp
代码如下:
- #include "CustomClasses.h"
- #include <QtCore>
- #include <QObject>
- TPerson::TPerson()
- {
- //
- }
- void TPerson::SetName(QString Name)
- {
- this->_Name=Name;
- }
- QString TPerson::GetName()
- {
- return this->_Name;
- }
- TSender::TSender()
- {
- this->_p.SetName("Jack");
- }
- void TSender::click()
- {
- qDebug()<<"now begin to send person";
- emit this->NewName(this->_p);
- qDebug()<<"Person has sended";
- }
- void TSender::disp()
- {
- qDebug()<<"current person name is:"<<this->_p.GetName();
- }
- TReceiver::TReceiver()
- {
- //
- }
- void TReceiver::GetNewName(TPerson P)
- {
- qDebug()<<"receive a person name is:"<<P.GetName();
- qDebug()<<"begin to change name";
- P.SetName("Rose");
- qDebug()<<"finish to change name";
- }
该文件是上述内容的实现,但值得注意的是,在void TReceiver::GetNewName(TPerson P)的实现中,对P参数进行了操作,调用了SetName方法。
主文件main.cpp
代码如下:
- #include <QtCore/QCoreApplication>
- #include <QtCore>
- #include <QObject>
- #include "CustomClasses.h"
- int main(int argc, char *argv[])
- {
- QCoreApplication a(argc, argv);
- TSender send;
- TReceiver recv;
- QObject::connect(&send, SIGNAL(NewName(TPerson)), &recv, SLOT(GetNewName(TPerson)));
- send.disp();
- send.click();
- send.disp();
- return a.exec();
- }
该代码实例化TSender类和TReceiver类,并绑定NewName信号与GetNewName槽。代码很简单,其他的就不再多做介绍了。
下面看运行结果:

我们来分析一下这个程序。在声明了send实例和recv实例后,绑定了相关事件。首先查看了一下当前send对象中的TPerson类实例 _p的Name属性。第一行显示的是初始的Jack;然后调用了send的click()方法,该方法放出了NewName信号,此时该信号被recv的GetNewName槽函数接收,该函数显示了当前接收到对象的Name值。然后调用了接收对象的SetName方法,将Name设置为“Rose”。槽函数执行完毕后,代码跳转到触发NewName信号的位置,即click()方法的“emit this->NewName(this->_p); ”后面;最后再显示一下send实例内部的_p实例Name属性。此时观察到虽然在槽函数中重新设置了Name属性,但并没有改变信号发起方实例的属性值(依旧是Jack)。因此我们可以说,这种传递对象的信号与槽机制是单向通信的。传递方向是信号发出方到信号接收方。当然这个例子中只是传递的一个对象,本人试验了一下,如果将上述代码进行小幅修改,将传递参数变为对象指针,则最终会影响到信号发送发的数据。如下图所示:

也就是说,如果传递的是指针,则该机制是双向通讯的,关键还是看如何去使用它们。我个人不推荐使用指针传递。因为一个信号可以绑定多个槽函数,若其中有一个对数据进行了修改,则会影响后续的槽函数执行,此时的参数状态未知,也不易于维护。当然了,什么事也不是绝对的,特殊情况下除外。
另外补充两点:
第一:上文中提到的“槽函数”这个词并不贴切。因为该方法是不能包含返回值的。必须是void,因此称之为“槽过程”比较贴切,但是已经广泛认同了这个叫法了,所以就没有深究。
第二:开始时为了图省事,将TPerson、TSender和TReceiver三个类的定义和实现都放到了main.cpp中。结果无论如何也编译不过去。提示“undefined reference vTable for class ...”, ...是这三个类的类名。后来查到资料得知在Qt程序编译时,遇到signal和slots定义的地方会调用moc工具对其进行转换,转换为标准c++代码(signal和slots不是标准C++的关键字),而moc工具是只识别.h文件的,因此还是老老实实用标准的C++类定义方法,别偷懒了吧:)
http://blog.csdn.net/chaijunkun/article/details/6249573
关于Qt信号与槽机制的传递方向性研究(结论其实是错误的,但是可以看看分析过程)的更多相关文章
- Qt信号和槽机制
概述 信号和槽机制是QT的核心机制,要精通QT编程就必须对信号和槽有所了解.信号和槽是一种高级接口,应用于对象之间的通信,他是QT的核心特性,也是QT差别于其他工具包的重要地方.信号和槽是QT自行定义 ...
- Qt信号与槽机制
一.信号和槽机制 信号和槽用于两个对象之间的通信,信号和槽机制是Qt的核心特征,也是Qt不同于其他开发框架的最突出的特征.在GUI编程中,当改变了一个部件时,总希望其他部件也能了解到该变化.更一般来说 ...
- QT的信号与槽机制介绍
信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工具以及在实际使用过程中应注意的一些问题. QT是一个跨平台的C++ GUI应用构架,它提供了丰富的窗 ...
- Qt 的信号与槽机制介绍(10个要注意的问题)
QT 是一个跨平台的 C++ GUI 应用构架,它提供了丰富的窗口部件集,具有面向对象.易于扩展.真正的组件编程等特点,更为引人注目的是目前 Linux 上最为流行的 KDE 桌面环境就是建立在 QT ...
- 自己用纯C++实现简单的QT中信号与槽机制
前天在我很久以前的一篇博文 (http://blog.csdn.net/liukang325/article/details/45742675) 中有人回复说看到我的博文很激动,希望我详细介绍一下信号 ...
- 【qt】QT 的信号与槽机制
QT 是一个跨平台的 C++ GUI 应用构架,它提供了丰富的窗口部件集,具有面向对象.易于扩展.真正的组件编程等特点,更为引人注目的是目前 Linux 上最为流行的 KDE 桌面环境就是建立在 QT ...
- QT的信号和槽机制简介
信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工具以及在实际使用过程中应注意的一些问题. QT是一个跨平台的C++ GUI应用构架,它提供了丰富的窗口部 ...
- QT从入门到入土(三)——信号和槽机制
摘要 信号槽是 Qt 框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号 (signal).这种发出是没有目的的,类似广播 ...
- qt中信号与槽机制
一. 简介 就我个人来理解,信号槽机制与Windows下消息机制类似,消息机制是基于回调函数,Qt中用信号与槽来代替函数指针,使程序更安全简洁. 信号和槽机制是 Qt 的核心机制,可以让编程人员将互不 ...
随机推荐
- HTML系列(六):划分文档结构
常见的网页结构布局是酱紫的,真是美美哒^O^: 一.添加基本标题h1~h6(没什么好说的): 二.标题分组hgroup <hgroup>用来将标题和子标题进行分组.如果一篇文章articl ...
- 创建Java项目报错处理
好久没用Eclipse编写Java程序了,今天创建一个Java项目的时候,老报错,错误信息如下: Implicit super constructor Object() is undefined fo ...
- .cs文件与aspx.cs文件之间的区别是什么???他们的作用是什么???ASPX文件的作用是什么?
一般在vs里面新建一个页面会产生两种文件:一种是后缀名为.cs的,一种是.aspx. 简单的说,.cs文件一般是在里面实现功能的,而.aspx就是实现界面效果的. 区别:.cs文件里面写的是.net的 ...
- Linux发展历史大事编年表(截止2013年)
这篇文章主要介绍了Linux发展历史大事编年表(截止2013年),Linux现在已经无处不在,是一个伟大的开原项目,让我一起来看看23年来它的发展历程吧 我们周围到处都有Linux的身影,在家中. ...
- java核心技术学习笔记之一程序设计环境
一术语 JDK:Java Delelpment Jit JRE:Java Runtime Environment 二.安装jdk1.8.0_25 设置环境变量(建议直接安装在C盘下),使用:隔开 C: ...
- Android面试笔试集锦
前19题为常考题目 1. Android的四大组件是哪些,它们的作用? 答:Activity:Activity是Android程序与用户交互的窗口,是Android构造块中最基本的一种,它需要为保持各 ...
- 贪吃蛇AI
贪吃蛇AI 作者:CodeNoob 转载请标明作者和出处 序言 前几天在网上看到一张让人涨姿势的图片,这张图片我很早以前看过,当时就觉得肯定是程序实现的,只是当时还比较渣,不会算法.这次学了java也 ...
- Drupal7模块multiselect使用
Drupal二次开发的时候,我们时常要使用到多选列表,但是官方默认的多选下拉列表,是在不敢恭维如下图所示: 不过难看不可怕,Drupal有两万第三方模块做支撑,只有你想不到,没有找不到的. 功夫不负有 ...
- c#SocketIO4NetClient访问node js
提到Node,不能错过的是WebSocket协议.它与Node之间的配合堪称完美,其理由有两条. 1.WebSocket客户端基于时间的编程模型与Node中自定义事件相差无几. 2.WebSocket ...
- 模式匹配-KMP算法
/***字符串匹配算法***/ #include<cstring> #include<iostream> using namespace std; #define OK 1 # ...