码迷,mamicode.com
首页 > 其他好文 > 详细

将接受子类指针的回调函数统一管理

时间:2017-12-16 11:12:53      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:间接   步骤   生成   base   情况   生成器   框架   完全   选项   

假设一个场景:收到网络协议的时候自动调用对应回调函数,回调函数的对象是协议参数。当我们处理不同的协议的时候需要不同的参数,那么我们只能让具体的参数继承自一个基类A。

这样一来我们就只能这样写回调函数

void fun(A* p)
{
    具体类型* param = (具体类型*)p;
    ……
}

这样一来回调函数的内部一般第一句话就是强转类型(或者用dynamic_cast也可以),与逻辑无关。

如果遇到了我这样有强迫症的人会不爽,怎么解决掉这个问题?

//假设已经有B类继承自A类
class Manager { public: using CallbackFunction = std::function<void(A*)>; template <class T> void Register(std::string key, std::function<void(T*)> callback) { static_assert(std::is_base_of<A, T>::value); _functions.insert(std::make_pair(key, [=](A* p) { callback((T*)p); })); } void Trigger(std::string key, A* param) { auto it = _functions.find(key); if (it != _functions.end()) it->second(param); } private: std::map<std::string, CallbackFunction> _functions; }; int main() { Manager m; auto cb = [](B* p) { std::cout << "in cb" << std::endl; }; m.Register<B>("B", cb); B* temp = new B; m.Trigger("B", temp); delete temp; return 0; }

 

因为使用了static_assert所以需要在编译选项中加入/std:c++latest

先讲讲static_assert,static_assert是静态断言,可以在编译期间对一些常量表达式之类的计算来实现断言,没有运行时期开销。

std::is_base_of定义于<type_traits>中,功能是判断一个类是否为一个类的子类,具体的判断方法是SFINA(匹配失败不是错误),用模板的方法判断是否具有继承关系。

 

实现这个功能的核心思路就是利用模板成员函数接受子类对象类型的回调函数,然后套上一个lambda,在lambda中强转基类类型然后调用接受子类对象类型的回调函数。

不过说实话,上面这段代码学习意义大于实际意义,因为一般情况下这种回调函数框架都是由代码生成器生成的(什么你告诉我你手写?再见。),完全可以把强转这个步骤放在生成器里面,一步到位。

而这种做法会有一层lambda的间接调用(或许编译器能够聪明到理解含义并且优化成一个强转),效率可能会略低一些。

将接受子类指针的回调函数统一管理

标签:间接   步骤   生成   base   情况   生成器   框架   完全   选项   

原文地址:http://www.cnblogs.com/reskai/p/8045348.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!