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 socket
        struct 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);      // 客户端port
                std::string clientip = ::inet_ntoa(peer.sin_addr); // 客户端ip

                std::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. 创建socket
    if(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. clientdone
    while(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# 
相关推荐
研☆香5 分钟前
js中使用的正则表达式
开发语言·javascript·正则表达式
szarron6 分钟前
国产手持式频谱分析仪选型攻略:TFN RC系列 vs HTOOL SA8T频谱分析仪 专业参数对比(军工/路测/调试全覆盖)
开发语言·前端·状态模式
我是唐青枫6 分钟前
C#.NET StructureMap 从依赖注入到项目实战
开发语言·c#·.net
Beyond_System|系统之外10 分钟前
一个网页如何同时适配投影仪、1366×768 和 1920×1080?我重新理解了“自适应布局”
开发语言·css·html
蛋先生DX10 分钟前
内存安全翻车现场的罪魁祸首,根源就在这三步里?
c++·后端·编程语言
小七在进步17 分钟前
C++入门(1)
java·jvm·c++
晴天的雨.99220 分钟前
[C++算法]快乐数
数据结构·c++·算法
Wang's Blog24 分钟前
Java框架快速入门: Spring Security+OAuth2之定制登录页
java·开发语言·spring
imgsq25 分钟前
MapLibre GL JS v6 正式发布:v5 之后八个月的第一个大版本(编译)
开发语言·javascript·ecmascript
统计学小王子25 分钟前
数学建模国赛倒计时 2 天 ——《缺失值处理一(R语言)》
开发语言·数学建模·r语言