C++ 回调函数
一、简单理解
函数指针
#include <iostream>
#include <string>void Server(std::string translation)
{std::cout << "I am a Server ,The words that the client needs to translate -> " << translation <<" <-> 苹果" << std::endl;
}
// 实现一个英文翻译 --> 这里先不这么复杂
// 客户端发来 apple
void Client(std::string word, void(*callback)(std::string))
{std::cout << "I am a client this English is: " << word << std::endl;callback(word);
}int main()
{Client("apple", Server);return 0;
}
function
using func_t = std::function<void(std::string)>;void Server(std::string translation)
{std::cout << "I am a Server ,The words that the client needs to translate -> " << translation <<" <-> 苹果" << std::endl;
}void Client(std::string word, func_t callback)
{std::cout << "I am a client this English is: " << word << std::endl;callback(word);
}int main()
{Client("apple", Server);return 0;
}
Lambda
using func_t = std::function<void(std::string)>;void Client(std::string word, func_t callback)
{std::cout << "I am a client this English is: " << word << std::endl;callback(word);
}
int main()
{Client("apple", [](std::string word) {std::cout << "I am a Server ,The words that the client needs to translate -> " << word << " <-> 苹果" << std::endl;});return 0;
}
仿函数
class Server
{
public:void operator()(std::string translation){std::cout << "I am a Server ,The words that the client needs to translate -> " << translation << " <-> 苹果" << std::endl;}
};void Client(std::string word, Server server)
{std::cout << "I am a client this English is: " << word << std::endl;server(word);
}int main()
{Server server;Client("apple", server);return 0;
}
所有函数的输出结果
I am a client this English is: apple
I am a Server ,The words that the client needs to translate -> apple <-> 苹果
二、实际应用
下面写一个很简单的回调实际应用
就是通过客户端发送一个apple,之后服务端通过回调进行发送一个苹果
UdpServer.h
using func_t = std::function<void(const std::string& , std::string* )>;class UdpServer
{
public:UdpServer(int port, func_t callback): _port(port), _sockfd(-1), _callback(callback){}~UdpServer(){if (_sockfd != -1){::close(_sockfd);}}bool Init(){// create socket_sockfd = socket(AF_INET, SOCK_DGRAM, 0);std::cout << "Create socket: " << _sockfd << std::endl;// bind socketstruct sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = ::htons(_port);local.sin_addr.s_addr = INADDR_ANY;int n = ::bind(_sockfd, (struct sockaddr *)(&local), sizeof(local));std::cout << "Bind socket success: " << n << std::endl;return true;}void Start(){while (true){char inbuffer[1024]; struct sockaddr_in peer;socklen_t len = sizeof(peer);// 接受数据ssize_t n = ::recvfrom(_sockfd, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr *)(&peer), &len);if (n > 0){inbuffer[n] = 0;uint16_t clientport = ::ntohs(peer.sin_port); // 客户端portstd::string clientip = ::inet_ntoa(peer.sin_addr); // 客户端ipstd::cout << "Received message from " << clientip << ":" << clientport << " sockfd: " << _sockfd << " Message: " << inbuffer << std::endl;std::string echo_string = "echo# ";echo_string += inbuffer;// 调用回调函数_callback(inbuffer, &echo_string);::sendto(_sockfd, echo_string.c_str(), echo_string.size(), 0, (struct sockaddr *)(&peer), len);}}}private:int _port;int _sockfd;func_t _callback;
};
Dict.h
class Translation
{
public:void translate(const std::string& word, std::string* transltion){std::cout << "client: " << word << std::endl;*transltion += " 苹果";}
};
UdpServer.cpp
int main(int argc,char *argv[])
{if(argc != 2){std::cerr << "Usage: "<< argv[0] << " serverip serverport" << std::endl;exit(1);}uint16_t serverport = std::stoi(argv[1]);Translation t;// 法一// auto callback = std::bind(&Translation::translate,&t,std::placeholders::_1,std::placeholders::_2);// UdpServer server(serverport,callback);// 法二UdpServer server(serverport,[&t] (const std::string& word, std::string* transltion) {t.translate(word, transltion);});server.Init();server.Start();return 0;
}
UdpClient.cpp
int main(int argc,char *argv[])
{if(argc != 3){std::cerr << "Usage: "<< argv[0] << " serverip serverport" << std::endl;exit(1);}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);int sockfd = ::socket(AF_INET,SOCK_DGRAM,0);// 1. 创建socketif(sockfd < 0){std::cerr << "socket error"<<std::endl;exit(1);}// 1.1填充信息struct sockaddr_in server;memset(&server,0,sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);server.sin_addr.s_addr = ::inet_addr(serverip.c_str());// 2. clientdonewhile(true){std::cout << "Please Enter# ";std::string message;std::getline(std::cin,message);int n = ::sendto(sockfd,message.c_str(),message.size(),0,(struct sockaddr*)(&server),sizeof(server));struct sockaddr_in temp;socklen_t len = sizeof(temp);char buffer[1024];n = :: recvfrom(sockfd,buffer,sizeof(buffer) - 1,0,(struct sockaddr*)(&temp),&len);if(n > 0){buffer[n] = 0;std::cout << buffer << std::endl;}}return 0;
}
这里只输出了客户端的消息
Please Enter# apple
echo# apple 苹果
Please Enter#