C++11实现Qt的信号槽机制
概述
Qt的信号槽机制是Qt的核心机制,按钮点击的响应、线程间通信等都是通过信号槽来实现的,boost里也有信号槽,但和Qt提供的使用接口很不一样,本文主要是用C++11来实现一个简单的信号槽,该信号槽也实现了emit、slots、signals、connect关键字和函数、使用方法和Qt的信号槽基本类似,该信号槽机制用到了C++11的特性有:
- 可变参数模板类
- 智能指针
- 函数相关std::function、std::bind
- using关键字
- 完美转发std::forward
该信号槽提供类成员函数、类非成员函数的连接、连接时支持std::bind、以及lambda表达式,信号槽机制的核心代码如下:
// Connect.hpp
#ifndef _CONNECT_H
#define _CONNECT_H
#include <vector>
#include <memory>
#include <functional>
#define emit
#define slots
#define signals public
#define connect(sender, signal, slot) ((sender)->signal.bind(slot))
template<typename... Args>
class Slot
{
public:
using OnFunc = std::function<void(Args&&...)>;
Slot(const OnFunc& func)
: m_func(func)
{
// Do nothing
}
void exec(Args&&... args)
{
m_func(std::forward<Args>(args)...);
}
private:
OnFunc m_func = nullptr;
};
template<typename... Args>
class Signal
{
public:
using SlotPtr = std::shared_ptr<Slot<Args&&...>>;
using OnFunc = std::function<void(Args&&...)>;
void bind(const OnFunc& func)
{
m_slotVec.push_back(SlotPtr(new Slot<Args&&...>(func)));
}
void operator()(Args&&... args)
{
for (auto& iter : m_slotVec)
{
iter->exec(std::forward<Args>(args)...);
}
}
private:
std::vector<SlotPtr> m_slotVec;
};
#endif
下面是使用C++11信号槽机制的代码:
// main.cpp
/************************************************
* 该例程讲解用C++11来实现Qt的信号槽机制
* 使用到的C++11特性有:
* 1.可变参数模板类
* 2.智能指针
* 3.函数相关std::function、std::bind
* 4.using关键字
* 5.完美转发std::forward
************************************************/
#include "Connect.hpp"
#include <iostream>
#include <string>
class A
{
public:
void start()
{
emit m_s1();
emit m_s2("Hello C++11");
emit m_s3(100, "Hello C++11");
}
signals:
Signal<> m_s1; // 不带参数的信号
Signal<std::string> m_s2;
Signal<int, std::string> m_s3;
};
class B
{
public slots:
void func1()
{
std::cout << "func1" << std::endl;
}
void func2(const std::string& str)
{
std::cout << str << std::endl;
}
void func3(int n, const std::string& str)
{
std::cout << n << " " << str << std::endl;
}
};
void func(const std::string& str)
{
std::cout << "func " << str << std::endl;
}
int main()
{
A a;
B b;
// 信号与槽绑定
connect(&a, m_s1, std::bind(&B::func1, &b));
connect(&a, m_s2, std::bind(&B::func2, &b, std::placeholders::_1));
connect(&a, m_s3, std::bind(&B::func3, &b, std::placeholders::_1, std::placeholders::_2));
connect(&a, m_s2, std::bind(func, std::placeholders::_1));
connect(&a, m_s2, [](const std::string& str)
{
std::cout << "lambda str: " << str << std::endl;
});
a.start();
return 0;
}
TODO
该例子只是实现了简单的信号槽机制,还有很多功能都没有实现
- 不支持断开信号与槽的连接disconnect
- 不支持AutoConnection、DirectConnection、QueuedConnection、UniqueConnection
- 不支持无锁连接
- etc...
该例子的github地址:https://github.com/chxuan/samples/tree/master/Connect
C++11实现Qt的信号槽机制的更多相关文章
- 非Qt工程使用Qt的信号槽机制
非Qt工程,使用Qt的信号槽机制,蛋疼不?反正我现在就是要做这样一件蛋疼的事. 要使用Qt的信号槽机制,下面是从Qt Assist里面关于 signal & slots 的一句介绍: All ...
- VJGUI消息设计-兼谈MFC、QT和信号/槽机制
星期六下午4点,还在公司加班.终于写完了下周要交工的一个程序. 郁闷,今天这几个小时写了有上千行代码吧?虽然大部分都是Ctrl-C+Ctrl-V,但还是郁闷. 作为一个有10年经验的MFC程序员,郁闷 ...
- Qt学习记录--02 Qt的信号槽机制介绍(含Qt5与Qt4的差异对比)
一 闲谈: 熟悉Window下编程的小伙伴们,对其消息机制并不陌生, 话说:一切皆消息.它可以很方便实现不同窗体之间的通信,然而MFC库将很多底层的消息都屏蔽了,尽管使用户更加方便.简易地处理消息,但 ...
- QT信号槽机制
信号槽 信号槽是QT中用于对象间通信的一种机制,也是QT的核心机制.在GUI编程中,我们经常需要在改变一个组件的同时,通知另一个组件做出响应.例如: 一开始我们的Find按钮是未激活的,用户输入要查找 ...
- QT写hello world 以及信号槽机制
QT是一个C++的库,不仅仅有GUI的库.首先写一个hello world吧.敲代码,从hello world 写起. #include<QtGui/QApplication> #incl ...
- 使用 C++11 编写类似 QT 的信号槽——上篇
了解 QT 的应该知道,QT 有一个信号槽 Singla-Slot 这样的东西.信号槽是 QT 的核心机制,用来替代函数指针,将不相关的对象绑定在一起,实现对象间的通信. 考虑为 Simple2D 添 ...
- Qt开发之信号槽机制
一.信号槽机制原理 1.如何声明信号槽 Qt头文件中一段的简化版: class Example: public QObject { Q_OBJECT signals: void customSigna ...
- QT源码之Qt信号槽机制与事件机制的联系
QT源码之Qt信号槽机制与事件机制的联系是本文要介绍的内容,通过解决一个问题,从中分析出的理论,先来看内容. 本文就是来解决一个问题,就是当signal和slot的连接为Qt::QueuedConne ...
- QT学习记录之理解信号槽机制
作者:朱金灿 来源:http://blog.csdn.net/clever101 QT的事件机制采用的信号槽机制.所谓信号槽机制,简而言之就是将信号和信号处理函数绑定在一起,比如一个按钮被单击是一个信 ...
随机推荐
- [翻译]创建ASP.NET WebApi RESTful 服务(7)
实现资源分页 本章我们将介绍几种不同的结果集分页方式,实现手工分页,然后将Response通过两个不同的方式进行格式化(通过Response的Envelop元数据或header). 大家都知道一次查询 ...
- NSLog中的%@
[NSLog中的%@] There is one additional substitution token available in Objective-C, %@, used to denote ...
- (转载)ETL利器Kettle实战应用解析系列一【Kettle使用介绍】
http://www.cnblogs.com/limengqiang/archive/2013/01/16/kettleapply1.html ETL利器Kettle实战应用解析系列一[Kettle使 ...
- unigui unidbgrid显示列的合计值
procedure TfrmClient.UniDBGrid1ColumnSummaryResult(Column: TUniDBGridColumn; GroupFieldValue: Varian ...
- 1001.A+B Format (20)(思路,bug发现及其修改,提交记录)
https://github.com/031502316a/object-oriented/tree/master/1001 ---恢复内容开始--- 1.解题思路 一开始见到题目时,感觉难的就是输出 ...
- GWT工程架构分析与理解
上一篇文章中介绍了GWT技术的一些理论性的东西,涉及到GWT得一些技术原理及实现.接下来笔者将通过创建一个GWT工程去理解分析GWT工程架构. GWT工程架构解析 笔者使用的是Eclipse插 ...
- C# 与 C++ 数据类型对照
C++ C#=====================================WORD ushortDWORD uintUCH ...
- ASP.NET MVC 4 中Jquery上传插件Uploadify简单使用-版本:3.2.1
1.官网下载开发包:http://www.uploadify.com/download/,选择免费的Flash版本: 2.解压后,需要用到以下几个文件: 需要修改uploadify.css中取消上传按 ...
- javascript js 内存泄露工具使用
javascript内存泄露工具使用 原文:http://lanhy2000.blog.163.com/blog/static/43678608201121472644851/ 2011-03-14 ...
- Win8增加了快速启动功能......
(从已经死了一次又一次终于挂掉的百度空间人工抢救出来的,发表日期 2014-05-11) Win8增加了快速启动功能,能让计算机尽快的启动进入Windows界面.win8的这种快速启动功能只会在“关机 ...