打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C 如何装饰函数实现代码最大程度复用

0 前言

Hello,大家好,欢迎来到『自由技艺』的 C++ 系列专题。代码重用,尽可能避免冗余代码是程序员的一项必备技能,今天就来给大家介绍其中一种:函数装饰器。在设计模式中,与它对应的是类的装饰器模式,但个人觉得很鸡肋,下回再说吧。

1 需求来源

现在假设有一个基础功能函数,但是呢,存在各种应用场景,每种场景都需要对这个函数小修小补、或增加一些定制化的功能。有几种处理方式呢?基类派生?函数重载?建造者模式?都不大合适,而函数装饰器就是一种可参考的手段。

void test(int a, int b) { std::cout << (a + b) << '\n';}void do_previous_work() { std::cout << 'do previous works' << '\n';}void do_after_work() { std::cout << 'do after works' << '\n';}template<typename RET, typename... ARGS>std::function<RET(ARGS... args)> decorator(RET(*p_func)(ARGS... args)) { return [&](ARGS... args) -> RET { do_previous_work(); test(args...); (*p_func)(args...); do_after_work(); }; //没有捕获任何变量的Lambda表达式可以转换成与它的调用原型一致的函数指针}int main() { int a = 10; int b = 20; f = test; f(a, b); // 第一次调用 f std::function<void(int, int)> f; f = decorator(test); f(a, b); // 第二次调用 f return 0;}

输出结果:

2 总结

上述代码中有一个基本函数 test,如果需要在 test 之前做某些事情(do_previous_work),在 test 之后也做一些事情(do_after_work),那么定义一个装饰器函数,把 test 封装下,再用函数对象接收就可以了。从结果上看,调用了 f 两次,却输出了不同的结果。如果再有其他需求,类似地再实现一个装饰器函数,同样用 f 接收,再调用,就可以了。

留个思考题,如果把装饰器函数写成如下形式:

template<typename RET, typename... ARGS>std::function<RET(ARGS... args)> decorator(RET(*p_func)(ARGS... args)) {    auto post = [&](ARGS... args) -> RET {        do_previous_work();        test(args...);        (*p_func)(args...);        do_after_work();    };    return post;}

这种写法有什么问题吗?欢迎留言区讨论~

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
C++雾中风景16:std::make_index_sequence, 来试一试新的黑魔法吧
【洛谷日报#110】浅谈C IO优化——读优输优方法集锦
又一个lua与C++粘合层框架
高端知识点:折叠表达式(我也是第一次知道)
一位Python初学者的独白:Python小白眼中的装饰器
stackless非栈式递归调用
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服