回调函数
什么是回调函数就不解释了,但为什么要开一篇来特别讲一下如何把类成员函数写回调函数?
如果回调函数是普通函数,其实普通函数就可以直接拿来当作回调函数,在设置回调函数中,注意与回调函数的返回值类型,参数列表一一对应即可
但类成员函数不同,在参数列表中,其实是隐藏了第一个指针型(void*)参数this
,这就会导致和设置回调函数的参数列表不匹配,没法成功安装
解决方法有三种
- 将回调函数设置为静态
- 将回调函数设置为友元
- 使用
bind
绑定
静态
TcpClient.h
typedef void(* RecvCallBack)(char*,int);
class TcpClient{
private:
static SOCKET sclient_;
public:
void SetRecvFunc(RecvCallBack );
static void RecvData(char* , int );
}
TcpClient.cpp
void TCPClient::SetRecvFunc(RecvCallBack Func) {
char buffer[1024];
while (1) {
int ret = recv(sclient, buffer, 1024, 0);
if (ret > 0) {
Func(buffer, ret);
memset(buffer, '\0', 1024);
}
else {
Sleep(1);
}
}
}
main.cpp
int main(){
TcpClient client = TcpClient("127.0.0.1",60000);
client.Initialize();
···
/*1.只运行一次*/
client.SetRecvFunc(&TcpClient::RecvData);
/*2.开线程*/
thread *thread_client_recv_data = new thread(&TcpClient::SetRecvFunc,&client,&TcpClient::RecvData);
thread_client_recv_data->detach();
}
static
类型的成员函数,无法通过对象调用,所以只能用类名来声明限定域——&TcpClient::
bind
绑定
因为静态
static
会破坏类的封装性,所以一般在项目中不使用,所以这里也一样
前面应该说过,其实这里的RecvData()
并不是要放在类中并且作为回调函数,只是当时自己理解错了,但阴差阳错学到了如何使用bind
绑定成员函数来改变函数的参数数量,所以才有这篇文章
而恰好成员函数没法直接用作回调函数的原因,最上面有提到,就是参数数量没法统一
TcpClient.h
#include <functional>
typedef function<void(char*, int)> RecvCallBack;
class TcpClient{
private:
···
public:
void RecvData(char*,int); // “回调函数”
function<void(char*,int)> Instead_RecvData = std::bind(&TcpClient::RecvData,this, placeholders::_1, placeholders::_2);
// 绑定后的函数
···
}
main.cpp
#include <functional>
int main(){
TcpClient client = TcpClient("127.0.0.1",60000);
client.Initialize();
/*1.只运行一次*/
client.SetRecvFunc(client.Instead_RecvData);
/*2.开线程*/
thread* thread_client_recv_data = new thread(&TcpClient::SetRecvFunc,&client,client.Instead_RecvData);
thread_client_recv_data->detach();
}
这里就记录下怎么用吧,反正网上一大堆讲解function
和bind
的,C++ bind与回调函数