IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 2021-08-05 -> 正文阅读

[开发测试]2021-08-05

C++模拟实现QT信号槽

为了看着更像QT的信号槽,我们也定义一个QObject的父类。

class QObject
{
public:
	QObject* self()
	{
		return this;
	}
	//获取信号的发送者
	std::function<QObject* (void)>  _sender;
};

信号的接收者

class Slot :public QObject
{
public:
	Slot() {}
public:
    //槽函数1
    //如需多个参数 可以将void* signal改为void **signal
	void slot1(void* signal)
	{   
	    //无法使用void*将signal强转为对应类型 使用*(reinterpret_cast<xxx*>(signal));接收
		double res = *(reinterpret_cast<double*>(signal));
		//signal可以强转为对应类型 直接强转即可
		//int res = (int)signal;
		if (_sender) {
		//获得了信号发送者的实例 
		/*
		do something
        */	
		}
		std::cout << "信号发送的参数 :" << res << " 接收者地址 :" << this << std::endl;
	}
	//槽函数2
	void slot2(void* signal) {
	 //无法使用void*将signal强转为对应类型 使用*(reinterpret_cast<xxx*>(signal));接收
		double res = *(reinterpret_cast<double*>(signal));
		//signal可以强转为对应类型 直接强转即可
		//int res = (int)signal;
		if (_sender) {
		//获得了信号发送者的实例 
		/*
		do something
        */	
		}
		std::cout << "信号发送的参数 :" << res << " 接收者地址 :" << this << std::endl;
	}
};

信号的发送者

class Signal :public QObject
{
public:
//如需多个参数 可以将void* signal改为void **signal
	void emitsignal(void *signal)
	{
	 //向信号的接收者传递实例
		_recver->_sender = std::bind(&Signal::self, this);
		string tres = __FUNCTION__;
		tres += "(";
		tres += typeid(signal).name();
		tres += ")";
		//由于没有实现QT的反射机制,暂且使用函数名及参数类型来获取对应的函数信息 tres值为Signal::emitsignal(void *signal)
		for (map<string, vector<function<void(Slot*, void*)>>>::iterator iter = callbacks.begin(); iter != callbacks.end(); iter++) {
		//遍历该函数信息对应的所有槽函数进行触发
			if (strcmp(iter->first.c_str(), tres.c_str()) == 0) {
				for (int i = 0; i < iter->second.size(); i++) {
					iter->second[i](_recver, signal);
				}
			}
		}

	}
	//存储信号和对应的槽函数集合
	map<string, vector<function<void(Slot*, void*)>>> callbacks;
	Slot* _recver;
};

连接函数Connect

//由于未能实现反射机制,先使用字符串ID来标识具体信号
//如需多个参数 可以将void* signal改为void **signal
void connect(Signal* sender, string signal, Slot* recver, function<void(Slot*, void*)> slot)
{
    //接收槽实例
	sender->_recver = recver;
	//向对应的信号中添加待触发的槽函数
	sender->callbacks[signal].push_back(slot);
}

所有代码及测试用例

#include <functional>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
//将参数x强制转换为为void*
#define SIG(x) const_cast<void*>(reinterpret_cast<void*>(x))
class QObject
{
public:
	QObject* self()
	{
		return this;
	}
	std::function<QObject* (void)>  _sender;
};
class Slot :public QObject
{
public:
	Slot() {}
public:

	void slot1(void* signal)
	{
       double res = *(reinterpret_cast<double*>(signal));
		//int res = (int)signal;
		if (_sender) {
		}
		std::cout << "信号发送的参数 :" << res << " 接收者地址 :" << this << std::endl;
	}
	void slot2(void* signal) {
		double res = *(reinterpret_cast<double*>(signal));
		if (_sender) {
		
		}
		std::cout << "信号发送的参数 :" << res << " 接收者地址 :" << this << std::endl;
	}
};

class Signal :public QObject
{
public:
	void emitsignal(void* signal)
	{
		_recver->_sender = std::bind(&Signal::self, this);
		string tres = __FUNCTION__;
		tres += "(";
		tres += typeid(signal).name();
		tres += ")";
		for (map<string, vector<function<void(Slot*, void*)>>>::iterator iter = callbacks.begin(); iter != callbacks.end(); iter++) {
			if (strcmp(iter->first.c_str(), tres.c_str()) == 0) {
				for (int i = 0; i < iter->second.size(); i++) {
					iter->second[i](_recver, signal);
				}
			}
		}

	}
	map<string, vector<function<void(Slot*, void*)>>> callbacks;
	Slot* _recver;
};
//连接函数
void connect(Signal* sender, string signal, Slot* recver, function<void(Slot*, void*)> slot)
{
	sender->_recver = recver;
	sender->callbacks[signal].push_back(slot);
}


int main()
{

	Signal signalobject;
	Slot   slotobject;
	connect(&signalobject, "Signal::emitsignal(void *)", &slotobject, &Slot::slot1);
	connect(&signalobject, "Signal::emitsignal(void *)", &slotobject, &Slot::slot2);
	//信号类型任意 只需与槽函数的参数对应即可
	double param = 10.25;
	signalobject.emitsignal(SIG(&param));
	//int param =10;
	//signalobject.emitsignal(SIG(10));
	return 0;
}

结果

在这里插入图片描述

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-08-06 10:07:54  更:2021-08-06 10:08:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 4:39:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码