C++11较为优雅的回调函数写法

管理类 所有的子模块都注册在这个类 这个类使用单例模式 使用回调来通知子模块
.h

#pragma once
#include "GUI.h"
#include "logic.h"
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
#include <memory>

using namespace std;

struct stActionCommand						//动作命令结构体
{
	int st_CommandFrom;						//命令来源
	int st_CommandType;						//命令类型
	int st_CommandSubType;					//子命令类型
	int st_CommandNumber;					//命令编号
	int st_Result;							//异步执行结果
	bool st_SynFlag;						//命令同步标识,true时必须等待执行返回,false时放入处理队列
	//输入数据
	void* st_InData;						//复杂输入数据
	int st_InEasyData1;						//简单输入数据1
	int st_InEasyData2;						//简单输入数据2
	unsigned long st_InULData;				//输入无符号长整型
	//输出数据
	void* st_OutData;						//复杂返回数据
	int st_OutEasyData1;					//简单返回数据1
	int st_OutEasyData2;					//简单返回数据2
};

class GUI;
class LOGIC;

class CallBackManage {
public:
	//单例模式
	static CallBackManage& getInstance();
	//初始化各个子模块指针
	void Init(void);
	//回调函数
	static void CallBackFunc(void* arg, int commandtype, stActionCommand* msg);
	//回调信息处理 但目前本人弃用了 选择在子模块进行异步操作
	void commandProcess(stActionCommand* msg);
	//提供给主程序的指针 但实际不需要 实际情况会有事件
	shared_ptr<void> getGuiPtr();
private:
	//构造函数
	CallBackManage() {

	}
	//弃用除构造函数的其他构造 保证线程安全
	CallBackManage(const CallBackManage& other) = delete;
	CallBackManage& operator =(const CallBackManage& other) = delete;
	queue<stActionCommand*> m_queue;
	//子模块指针
	shared_ptr<GUI> m_guiPtr;
	shared_ptr<LOGIC> m_logicPtr;
};

.cpp

#include "CallBackManage.h"

CallBackManage& CallBackManage::getInstance() {
	static CallBackManage instance;
	return instance;
}

void CallBackManage::Init(void) {
	m_guiPtr = make_shared<GUI>();
	m_logicPtr = make_shared<LOGIC>();
	m_guiPtr->init();
	m_logicPtr->init();
}

void CallBackManage::CallBackFunc(void* arg, int commandtype, stActionCommand* msg) {
	cout << "CallBack Manage" << endl;
	CallBackManage* lp = (CallBackManage*)arg;
	cout << lp << "lp" << commandtype << "type" << msg << "msg" << endl;

	switch (commandtype) {
	case 0:
		lp->m_logicPtr->guiButtonClicked(msg);
		break;
	case 1:
		lp->m_guiPtr->LogicReceived(msg);
		break;
	}
	//if (!msg->st_SynFlag) {//异步 这里改为根据type发给子模块比较好 不需要对它进行区分  屏蔽细节
	//	//或者改为线程池 根据任务的等级进行区分   感觉还是分给模块比较好  
	//	lp->commandProcess(msg);
	//}
	//else {//同步

	//}
}

void CallBackManage::commandProcess(stActionCommand* msg) {
	stActionCommand* iTempAC = new stActionCommand;
	memcpy(iTempAC, msg, sizeof(stActionCommand));
	m_queue.push(iTempAC);
}

shared_ptr<void> CallBackManage::getGuiPtr() {
	return m_guiPtr;
}

gui模块.h

#pragma once
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
#include <memory>
#include "CallBackManage.h"
using namespace std;

extern struct stActionCommand;

class GUI {
public:
	GUI() {
	}

	~GUI() {

	}

	void init();


	int ButtonClicked(void);

	int LogicReceived(stActionCommand* msg);
private:
	function<void(void*, int, stActionCommand*)> m_callBack;
	void* m_process;
};

gui模块.cpp

#include "GUI.h"

void GUI::init() {
	m_process = &CallBackManage::getInstance();
	m_callBack = CallBackManage::CallBackFunc;
}


int GUI::ButtonClicked(void) {
	if (m_callBack) {
		stActionCommand temp;//生命周期在这一段 回调函数之后 所以回调函数的指针是完全可以的 不会成为悬垂指针
		m_callBack(m_process, 0, &temp);
		return 0;
	}
	cout << "empty" << endl;
	return -1;
}

int GUI::LogicReceived(stActionCommand* msg) {
	cout << "LOGIC handle the msg" << endl;
	return 0;
}

logic模块.h

#pragma once
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
#include <memory>
#include "CallBackManage.h"
#include <thread>
using namespace std;

extern struct stActionCommand;


class LOGIC {
public:
	LOGIC() {
	}

	~LOGIC() {
		exit = true;
	}

	void init();

	int guiButtonClicked(stActionCommand* msg);

	static void asynCommand(void* lobject);
	void asynCommandProcess(void);

	void processCommand(stActionCommand* msg);
private:
	function<void(void*, int, stActionCommand*)> m_callBack;
	void* m_process;
	queue<stActionCommand*> m_queue;
	thread* m_commandAsyn;
	bool exit;
};

logic模块.cpp

#include "logic.h"

void LOGIC::init() {
	m_process = &CallBackManage::getInstance();
	m_callBack = CallBackManage::CallBackFunc;
	cout << "size" << m_queue.size() << endl;;
	m_commandAsyn = new thread(LOGIC::asynCommand, this);
	exit = false;
	
}

int LOGIC::guiButtonClicked(stActionCommand* msg) {
	if (!msg->st_SynFlag) {
		stActionCommand* iTempAC = new stActionCommand;
		memcpy(iTempAC, msg, sizeof(stActionCommand));
		m_queue.push(iTempAC);//然后再启动一个线程来处理这个queue
	}
	else {
		switch (msg->st_CommandType) {
		case 0:
			cout << "hello i'm hurry" << endl;
			break;
		}
	}


	if (m_callBack) {
		stActionCommand temp;//生命周期在这一段 回调函数之后
		//往temp里面填充信息就行
		m_callBack(m_process, 1, &temp);
		return 0;
	}
	cout << " guiButtonClicked empty" << endl;
	return -1;

}


void LOGIC::asynCommand(void* lobject) {
	LOGIC* lp = (LOGIC*)lobject;
	lp->asynCommandProcess();
}

void LOGIC::asynCommandProcess(void) {
	while (!exit) {
		if (!m_queue.empty())
		{
			stActionCommand* iTempAC = m_queue.front();
			processCommand(iTempAC);
			m_queue.pop();
			delete iTempAC;
			iTempAC = NULL;
		}
		//_sleep(300);
		for (int i = 0; i < 1000 ; i ++) {

		}
	}
}

void LOGIC::processCommand(stActionCommand* msg) {
	switch (msg->st_CommandNumber) {
	case 0:
		//do something
		break;
	}
}

test

int main() {
	//LOGIC* temp = new LOGIC();
	CallBackManage::getInstance();
	CallBackManage::getInstance().Init();
	auto ptr = static_pointer_cast<GUI>(CallBackManage::getInstance().getGuiPtr());//没办法 只能这样模拟事件了
	ptr->ButtonClicked();
	system("pause");
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值