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# 
相关推荐
奇树谦2 分钟前
VTK|显示三维图像的二维切片
c++·vtk·qt5·三维显示
yorushika_5 分钟前
python打卡训练营打卡记录day30
开发语言·python
老歌老听老掉牙19 分钟前
Open CASCADE学习|几何体切片处理:OpenMP与OSD_Parallel并行方案深度解析
c++·学习·open cascade·切片处理
文莉wenliii36 分钟前
打卡day30
开发语言·python
Forest_HAHA43 分钟前
QT——概述
开发语言·qt
superior tigre1 小时前
C++学习:六个月从基础到就业——C++20:范围(Ranges)基础
c++·学习·c++20
yuanpan1 小时前
支持python的单片机有哪些
开发语言·python·单片机
欧先生^_^1 小时前
Rust 编程语言的官方源码仓库
开发语言·算法·rust
蓝瓶电液1 小时前
星际争霸小程序:用Java实现策略模式的星际大战
java·开发语言·策略模式
fashia2 小时前
Java转Go日记(三十九):Gorm查询
开发语言·后端·golang·go