概述

Qt的信号槽机制是Qt的核心机制,按钮点击的响应、线程间通信等都是通过信号槽来实现的,boost里也有信号槽,但和Qt提供的使用接口很不一样,本文主要是用C++11来实现一个简单的信号槽,该信号槽也实现了emit、slots、signals、connect关键字和函数、使用方法和Qt的信号槽基本类似,该信号槽机制用到了C++11的特性有:

  1. 可变参数模板类
  2. 智能指针
  3. 函数相关std::function、std::bind
  4. using关键字
  5. 完美转发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

该例子只是实现了简单的信号槽机制,还有很多功能都没有实现

  1. 不支持断开信号与槽的连接disconnect
  2. 不支持AutoConnection、DirectConnection、QueuedConnection、UniqueConnection
  3. 不支持无锁连接
  4. etc...

该例子的github地址:https://github.com/chxuan/samples/tree/master/Connect

C++11实现Qt的信号槽机制的更多相关文章

  1. 非Qt工程使用Qt的信号槽机制

    非Qt工程,使用Qt的信号槽机制,蛋疼不?反正我现在就是要做这样一件蛋疼的事. 要使用Qt的信号槽机制,下面是从Qt Assist里面关于 signal & slots 的一句介绍: All ...

  2. VJGUI消息设计-兼谈MFC、QT和信号/槽机制

    星期六下午4点,还在公司加班.终于写完了下周要交工的一个程序. 郁闷,今天这几个小时写了有上千行代码吧?虽然大部分都是Ctrl-C+Ctrl-V,但还是郁闷. 作为一个有10年经验的MFC程序员,郁闷 ...

  3. Qt学习记录--02 Qt的信号槽机制介绍(含Qt5与Qt4的差异对比)

    一 闲谈: 熟悉Window下编程的小伙伴们,对其消息机制并不陌生, 话说:一切皆消息.它可以很方便实现不同窗体之间的通信,然而MFC库将很多底层的消息都屏蔽了,尽管使用户更加方便.简易地处理消息,但 ...

  4. QT信号槽机制

    信号槽 信号槽是QT中用于对象间通信的一种机制,也是QT的核心机制.在GUI编程中,我们经常需要在改变一个组件的同时,通知另一个组件做出响应.例如: 一开始我们的Find按钮是未激活的,用户输入要查找 ...

  5. QT写hello world 以及信号槽机制

    QT是一个C++的库,不仅仅有GUI的库.首先写一个hello world吧.敲代码,从hello world 写起. #include<QtGui/QApplication> #incl ...

  6. 使用 C++11 编写类似 QT 的信号槽——上篇

    了解 QT 的应该知道,QT 有一个信号槽 Singla-Slot 这样的东西.信号槽是 QT 的核心机制,用来替代函数指针,将不相关的对象绑定在一起,实现对象间的通信. 考虑为 Simple2D 添 ...

  7. Qt开发之信号槽机制

    一.信号槽机制原理 1.如何声明信号槽 Qt头文件中一段的简化版: class Example: public QObject { Q_OBJECT signals: void customSigna ...

  8. QT源码之Qt信号槽机制与事件机制的联系

    QT源码之Qt信号槽机制与事件机制的联系是本文要介绍的内容,通过解决一个问题,从中分析出的理论,先来看内容. 本文就是来解决一个问题,就是当signal和slot的连接为Qt::QueuedConne ...

  9. QT学习记录之理解信号槽机制

    作者:朱金灿 来源:http://blog.csdn.net/clever101 QT的事件机制采用的信号槽机制.所谓信号槽机制,简而言之就是将信号和信号处理函数绑定在一起,比如一个按钮被单击是一个信 ...

随机推荐

  1. flex编译命令相关

    最近碰到几次flex组件集版本问题,mx容器包含s组件,错误百出,会一直提示皮肤文件错误,上网查了一下,只要在工程属性中--->Flex编译器--->附加的编译参数中加入如下命令行即可:- ...

  2. 轻松学习Linux之理解Shell的硬链接与软连接

     大家在学习linux的过程中常常遇到一些模糊且容易混淆的概念比如什么是硬链接和软链接,他们有什么区别?  软连接有点象windows中的快捷方式,连接和目标文件具有相同的节点,而硬连接就好象重新复制 ...

  3. <一道题>abc+cba=1333,求满足条件的abc的值,隐含条件a!=0,c!=0

    这类东西,无非就是穷举法.见下面代码: #include <stdio.h> #include <stdlib.h> /* *abc + cba = 1333 * *a = ? ...

  4. 实时监控MySql状态

    大多网站的性能瓶颈都会出在数据库上,所以想把Mysql监控起来,就搜索了下相关资料. 后来和同事讨论了下cacti和nagios有些老套和过时,graphite比较时尚,然后就搜了下相关的资料,最后搞 ...

  5. UVaLive 6608 Cabin Baggage (水题)

    题意:给定四个数代表长宽高和重,问你是不是满足下面条件,长不高于56,宽不宽于45,高不高于25,或者总和不大于125,并且重量不高于7. 析:判断输出就好,注意这个题是或,不要想错了. 代码如下: ...

  6. C#调用C++编写的dll库

    我用vs2008建的C++ dll类库,名字test_interopVC,和C#的CeshiVC项目 一:C++项目dll类库: 1.test_interopVC.h,主要简单的测试,所以就在一个类里 ...

  7. hdoj 5335 Walk Out

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5335 #include<stdio.h> #include<cstring> ...

  8. 一个可创建读取日志的管理类(可固定创建2M大小的日志文件)

    这里,将日志管理基类命名为LogManagerBase(抽象类),具体的不同类型的日志可以通过继承完成.该基类可将日志以每个2M的方式存储起来,并可以读取当前正在使用的日志的所有内容. 要实现该基类, ...

  9. 你真的会玩SQL吗?实用函数方汇总

    http://www.cnblogs.com/zhangs1986/p/4917800.html 实用函数方法 由于有些知识很少被用到,但真需要用时却忘记了又焦头烂额的到处找. 现在将这些‘冷门“却有 ...

  10. 快速找到跟踪其他session产生的trc文件

    掌握该技术最根本的是需要搞清楚session跟踪文件存放的路径和生成跟踪文件的命名规则,不然,在已经存在成全上万trc文件的生产环境中,要想快速正确的找到跟踪其他SESSION产生的trc文件就如大海 ...