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# 
相关推荐
艾莉丝努力练剑1 分钟前
【C语言】学习过程教训与经验杂谈:思想准备、知识回顾(三)
c语言·开发语言·数据结构·学习·算法
ZZZS051610 分钟前
stack栈练习
c++·笔记·学习·算法·动态规划
位东风33 分钟前
【c++学习记录】状态模式,实现一个登陆功能
c++·学习·状态模式
witton1 小时前
Go语言网络游戏服务器模块化编程
服务器·开发语言·游戏·golang·origin·模块化·耦合
枯萎穿心攻击2 小时前
ECS由浅入深第三节:进阶?System 的行为与复杂交互模式
开发语言·unity·c#·游戏引擎
Jerry Lau2 小时前
go go go 出发咯 - go web开发入门系列(一) helloworld
开发语言·前端·golang
nananaij2 小时前
【Python基础入门 re模块实现正则表达式操作】
开发语言·python·正则表达式
Micro麦可乐2 小时前
Java常用加密算法详解与实战代码 - 附可直接运行的测试示例
java·开发语言·加密算法·aes加解密·rsa加解密·hash算法
天下一般2 小时前
go入门 - day1 - 环境搭建
开发语言·后端·golang
雷羿 LexChien3 小时前
C++内存泄漏排查
开发语言·c++