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的事件机制采用的信号槽机制.所谓信号槽机制,简而言之就是将信号和信号处理函数绑定在一起,比如一个按钮被单击是一个信 ...
随机推荐
- dom 关键字提示
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- SQL Server常用元数据函数
元数据函数 1.获取数据库标识符DB_ID DB_ID函数用于获取当前数据库的唯一ID(int数据类型),数据库ID用于服务器上唯一区分书库. 语法结构: DB_ID (['database_name ...
- JavaScript 变量、作用域及内存详解
基本类型值有:undefined,NUll,Boolean,Number和String,这些类型分别在内存中占有固定的大小空间,他们的值保存在栈空间,我们通过按值来访问的. (1)值类型:数值.布尔值 ...
- 转】MyEclipse使用总结——MyEclipse中配置WebLogic12c服务器
原博文出自于:http://www.cnblogs.com/xdp-gacl/p/4142495.html 感谢! MyEclipse中配置WebLogic12c服务器的步骤如下: [Window]→ ...
- C#完整的通信代码(点对点,点对多,同步,异步,UDP,TCP)
C# code namespace UDPServer { class Program { static void Main(string[] args) { int recv; byte[] dat ...
- XSLT模糊查询函数contains不区分大小写,for-each排序
代码如下: <xsl:for-each select="//NewDataSet/map/area[contains(translate(@alt, 'ABCDEFGHIJKLMNOP ...
- C# List 中 Find 方法
实例化一个集合 List<User> userCollection = new List<User>(); userCollection.Add(new User(1, &qu ...
- js时间转换相关
1.json时间格式转换 function ChangeDateFormat(jsondate) { if (!jsondate||jsondate.length < 1) {return &q ...
- Gson 和 Fastjson 你不知道的事
背景 目前在公司负责的业务, 主要是跟JSON数据打交道, fastjson .gson都用, 他们适用于不同场景.fastjson号称是业界处理json效率最高的框架, 没有之一.但在某些场景下, ...
- 用jquery判断当前显示器的分辨率,加载不同CSS
<link rel="stylesheet" type="text/css" id="css"><script langu ...