Qt Inside 之信号和槽原理概述

栏目: IT技术 · 发布时间: 4年前

内容简介:提到Qt,大家首先想到的可能就是信号和槽通信,但是他们是如何实现的呢?本系列内容就和大家一起探究Qt信号槽通信机制的原理。Qt环境:

提到Qt,大家首先想到的可能就是信号和槽通信,但是他们是如何实现的呢?

本系列内容就和大家一起探究Qt信号槽通信机制的原理。

Qt环境: Qt5.5.1

高版本Qt又增加了很多宏,不方便初学者理解。

一、  官方信号槽例子

1. 头文件

#include <QObject>


class Counter : public QObject

{

Q_OBJECT

public:

explicit Counter() {m_value = 0;}


public:

int value() const { return m_value; }


signals:

void signal_valueChanged(int newValue);


public slots:

void slot_setValue(int value);



private:

int m_value;

};

2. 源文件

void Counter::slot_setValue(int value)

{

if (value != m_value) {

m_value = value;

emit signal_valueChanged(value);

}

}

3. main函数中调用及结果

Counter a, b;

QObject::connect(&a, SIGNAL(signal_valueChanged(int)),

&b, SLOT(slot_setValue(int)));


a.slot_setValue(12); //a.value() = 12, b.value() = 12

b.slot_setValue(48); //a.value() = 12, b.value() = 48

这是最初的语法,从 1992 年 Qt 发明以来就没有变化。

但是,即使从一开始最基本的 API 没有改变,其底层实现被修改过好多次。在底层添加了许多新的特性,也有很多内容发生了变化。不过,即便如此,也并没有引入任何魔法,接下来我们将慢慢剖析。

二、  MOC ——元对象编译器

 我们知道信号槽使用的前提是继承QObject或其子类并且声明了 Q_OBJECT 宏。

但是这个宏是谁解析的呢?

Qt信号槽和属性系统【不做扩展】是基于运行时的自省能力。 Qt 开发时 C++ 并没有 Qt 所需要的内省能力,所以 Qt 便自己扩展了 C++ ,提供了这种能力—— MOC ,元对象编译器。

它处理头文件,重新生成C++文件,将这些文件连同剩余的 C++ 文件再一起编译。这些新生成的文件包含了内省所需要的信息。

三. 那些熟悉的宏

下面的这些关键字显示都不是标准C++所能识别的,但是我们在编译时为什么没有报错呢?因为它们都是一些宏,在 qobjectdefs.h 中定义。

signals 、 slotsemitSIGNALSLOT

#    define   slots

#    define   signals   public

槽函数就是普通的函数,编译器对他们就像对待其他函数一样。这些宏的另外一个目的是它们可以被MOC识别。

信号函数的代码由MOC生成,并且没有返回值。

#    define   emit

emit是一个空宏,而且 MOC 也不会处理它。所以当我们发出信号时可以无需加 emit ,但是为了提高代码的可读性,通常都是加上 emit 关键字的。

Q_CORE_EXPORT const char *qFlagLocation(const char *method);


#ifndef QT_NO_META_MACROS

#ifndef QT_NO_DEBUG

# define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__)

# ifndef QT_NO_KEYWORDS

# define METHOD(a) qFlagLocation("0"#a QLOCATION)

# endif

# define SLOT(a) qFlagLocation("1"#a QLOCATION)

# define SIGNAL(a) qFlagLocation("2"#a QLOCATION)

#else

# ifndef QT_NO_KEYWORDS

# define METHOD(a) "0"#a

# endif

# define SLOT(a) "1"#a

# define SIGNAL(a) "2"#a

#endif

   这些宏仅由预处理器使用,将参数转换成字符串,并且在之前添加一个代码。

在调试模式下,我们还会将这些字符串追加上所在文件的位置作为信号无法正常连接的警告信息。关于一些宏的用法大家可自行查询,或者直接编码查看效果。

#define Q_OBJECT \

public: \

Q_OBJECT_CHECK \

QT_WARNING_PUSH \

Q_OBJECT_NO_OVERRIDE_WARNING \

static const QMetaObject staticMetaObject; \

virtual const QMetaObject *metaObject() const; \

virtual void *qt_metacast(const char *); \

virtual int qt_metacall(QMetaObject::Call, int, void **); \

QT_WARNING_POP \

QT_TR_FUNCTIONS \

private: \

Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \

struct QPrivateSignal {};

Q_OBJECT宏定义了一个静态的 staticMetaObject 对象和一系列其他的函数,这些将由 MOC生成的moc_**.cpp中实现。

四、小结

看到这块大家可能会比较疑惑,这些是和信号槽有一些关系,但是根本无法看出信号和槽的原理啊!的确是这样的,无法看出来。

欲知后事如何,关注公众号后且听下回分解。

Qt Inside 之信号和槽原理概述


以上所述就是小编给大家介绍的《Qt Inside 之信号和槽原理概述》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

大数据之路

大数据之路

阿里巴巴数据技术及产品部 / 电子工业出版社 / 2017-7-1 / CNY 79.00

在阿里巴巴集团内,数据人员面临的现实情况是:集团数据存储已经达到EB级别,部分单张表每天的数据记录数高达几千亿条;在2016年“双11购物狂欢节”的24小时中,支付金额达到了1207亿元人民币,支付峰值高达12万笔/秒,下单峰值达17.5万笔/秒,媒体直播大屏处理的总数据量高达百亿级别且所有数据都需要做到实时、准确地对外披露……巨大的信息量给数据采集、存储和计算都带来了极大的挑战。 《大数据......一起来看看 《大数据之路》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具