c++关于回调函数和typedef

先看看typedef的用法

tepdef是系统保留字,可以为指针定义简介的名称,如

typedef int (*MyFUN)(int a,intb);
int Max(int a,int b);
MyFUN pMyFun;
pMyFun= Max;

其中MyFUN代表指向函数的指针类型的新名称,为指向函数的指针的类型别名。

  • 再说一下复杂声明的分析
    理解复杂声明可用的“右左法则”:从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完

举个例子

int (*func[5])(int *);

func右边是一个[ ]运算符,说明func是具有5个元素的数组;func的左边有一个*,说明func[ ] 的元素是指针(注意这里的不是修饰 func,而是修饰func[5]的,原因是[ ]运算符优先级比高,func先跟[ ]结合)。跳出这个括号,看右边,又遇到圆括号,说明func数组的元素是函数类型的指针,它指向的函数具有int*类型的形参,返回值类型为int。

  • C++回调
    在C++中,服务器编程常使用线程池+任务回调,需要用函数指针。
#include <cstdio>//第一步,声明函数指针。下面是声明一个函数指针,这个函数指针的类型名叫func,它指向的函数返回值为void,调用的参数为inttypedef void(*func)(int);
​
​
​
void Print(int i ){
  printf("%d\n", i);
}int main () {//  第二步,定义一个函数指针,并且指向一个符合函数指针声明的函数
​
    func f = &Print;
    f(1);  //调用函数
    return 0;
}

如果想加点面向对象的思想,我们可以多定义一个结构体,然后把回调的函数指针和调用的参数给封装起来

typedef void(*func)(int);struct  MyStruct{int param;
​
    func callback;}:

在看一个服务器项目中的例子:
我的主线程中的一个epoll事件是如果服务端关闭连接,删除对应的套接字数据。
先看看自定义的用户数据结构client_data

class util_timer;

struct client_data
{
    sockaddr_in address;
    int sockfd;
    //用户数据类里面的成员对象包含了回调函数的指针,便于之后使用
    util_timer *timer;
};

class util_timer
{
public:
    util_timer() : prev(NULL), next(NULL) {}

public:
    time_t expire;
    
    void (* cb_func)(client_data *);
    client_data *user_data;
    util_timer *prev;
    util_timer *next;
};

主线程中定义的回调函数,以及逻辑

void cb_func(client_data *user_data)
{
    epoll_ctl(epollfd, EPOLL_CTL_DEL, user_data->sockfd, 0);
    assert(user_data);
    close(user_data->sockfd);
    http_conn::m_user_count--;
    LOG_INFO("close fd %d", user_data->sockfd);
    Log::get_instance()->flush();
}
 client_data *users_timer = new client_data[MAX_FD];
 //...
 //为每个连接注册回调函数
 for() {
       users[connfd].init(connfd, client_address);
       util_timer *timer = new util_timer;
       timer->user_data = &users_timer[connfd];
	}
//...
 else if (events[i].events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR))
            {
                //服务器端关闭连接,移除对应的定时器
                util_timer *timer = users_timer[sockfd].timer;
                timer->cb_func(&users_timer[sockfd]);//回调函数的调用

                if (timer)
                {
                    timer_lst.del_timer(timer);
                }
            }

实际中大概就是这样的过程,之前一直没有太理解:为什么必须用指针的形式,对于特定的业务逻辑我直接调用函数不行么?理论上其实也可以,但是这样在复杂的项目也会比较臃肿,用指针的形式有点类似与函数形式的多态,相当于我只要写好形参即可,至于被调用函数的实际定义可能暂时不确定,或者不是我写/有多种形式等等,指针形式回调函数可以解决这个问题。通俗来说提供了一个接口。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值