当前位置: 首页 > news >正文

跟我学C++中级篇——链式调用的实践

一、链式调用

在前面的文章中,已经对链式调用有了不少的了解。比如“ this指针”和“设计模式”以及C++23中显式this等文章中都多少有些涉及。但实际上,C++对链式调用的支持并不多给力。如果有Java特别是Kotlin语言开发经验的,对链式调用应该是非常容易理解的。
所谓链式调用,就是像链表一样,将函数的调用连接起来,即可以连续调用多个函数。它让代码看起来更直白、易维护。不过如果调用链太深,反而让开发者有点感觉到莫名其妙。这也是事物的两面性吧。链式调用更符合自然语言,所以在一些函数编程语言以及高级语言中应用非常广泛。C++中的链式调用应用并没有其它语言那么广泛,这也是C++语言本身的一些特点和应用场景限制的。

二、运行机制和原理

链式调用的原理本质是对对象引用或指针的控制和处理。链式调用需要在每次完成后继续调用相关的函数,就必须得到函数所在的对象,进而才能够进行下一步的函数调用。所以链式调用的核心机制就是保证必须能够通过上一个函数调用返回应用对象的引用或指针,从而确保连续调用的函数影响作用到对象的同一实例(某些扩展实现可能不是这种情况)。

三、实现方式

实现链式调用对于C++这类语言来说并不复杂,但也并如函数式语言那么简单。其主要的实现方式包括:

  1. 对象引用和指针的操作
    在函数的返回值中通过返回指针(this)或 引用(*this)的方式来传回同一对象实例。这是最常用的方法:
class Demo{public:Demo*setColor(intv){color_=v;returnthis;}Demo*setHigh(intv){high_=v;returnthis;}private:intcolor_=0;inthigh_=160;};intmain(){Demo d;d.setColor(255)->setHigh(180);return0;}
  1. 流畅接口实现(Fluent Interface)
    流畅式接口的设计实现其实更倾向于从逻辑上对链式调用的实现,实际实现并未脱离链式调用实现的基本方法。以一个电商的操作为例:
#include<iostream>#include<string>#include<vector>class OnShoppingCart{private:std::vector<std::string>itemName_;std::string userName_;public:OnShoppingCart&getUser(conststd::string&userName){userName_=userName;return*this;}OnShoppingCart&addItem(conststd::string&itemName){itemName_.push_back(itemName);return*this;}};intmain(){OnShoppingCart cart;cart.getUser("iPad").addItem("iPhone").addItem("iWatch");return0;}
  1. 运算符重载实现
    这种实现非常常见,比如std::cout中对<<操作符的重载,看下面的简单例子:
#include<string>class Demo{public:Demo*setColor(intv){color_=v;returnthis;}Demo*setHigh(intv){high_=v;returnthis;}Demo&operator<<(conststd::string&msg){msg_+=msg;return*this;}private:intcolor_=0;inthigh_=160;std::string msg_="";};intmain(){Demo d;d<<"hello "<<"world!";return0;}
  1. 模板中的CRTP实现
    这个在前面有专门的论述,可参看相关“CRTP”的文章,下面看例子:
template<typename ConcretePrinter>class Printer{public:Printer(std::ostream&pstream):stream_(pstream){}template<typename T>ConcretePrinter&print(T&&t){stream_<<t;returnstatic_cast<ConcretePrinter&>(*this);}template<typename T>ConcretePrinter&println(T&&t){stream_<<t<<std::endl;returnstatic_cast<ConcretePrinter&>(*this);}private:std::ostream&stream_;};enumColor{red,blue,green};class CoutPrinter:public Printer<CoutPrinter>{public:CoutPrinter():Printer(std::cout){}CoutPrinter&SetConsoleColor(Color c){return*this;}};voidTestChain(){CoutPrinter().print("Hello ").SetConsoleColor(Color::red).println("Printer!");}intmain(){TestChain();return0;}

CRTP对于大多数的开发者可能觉得有点陌生,不想深入学习模板技术的可以只知道有这么一回事即可,不必深究。

四、应用场景

链式调用的应用场景其实也不算少,主要有:

  1. 设计模式中的应用
    比如常见的建造者模式、流畅接口模式等。
  2. 异步调用
    在异步调用中可以使用链式调用来处理回调,让代码更简洁和方便
  3. 发布-订阅机制
    通过事件驱动消息的链式调用发送

链式调用优点明显但也有不少的缺点,典型的就是链式调用过程中出现异常的处理比较复杂,另外一个就是调试过程中复杂的来回跳转,增加了调试中的困难。这些大家要根据情况自行评估应用。

五、例程

在上面学习的基础上,看一个比较典型的观察者模式中对事件通知的处理:

#include<iostream>#include<functional>#include<vector>#include<string>#include<memory>#include<algorithm>class Observer{public:virtual~Observer()=default;virtualvoidonEvent(conststd::string&event,conststd::string&task)=0;};class TaskObserver:public Observer{private:std::string runnerName_;public:TaskObserver(conststd::string&name):runnerName_(name){}voidonEvent(conststd::string&event,conststd::string&task)override{std::cout<<runnerName_<<"Event: "<<event<<", task: "<<task<<std::endl;}};class EventControl{private:std::vector<std::shared_ptr<Observer>>observers_;public:EventControl&insertObserver(std::shared_ptr<Observer>ob){observers_.push_back(ob);return*this;}EventControl&delObserver(std::shared_ptr<Observer>ob){autoit=std::remove(observers_.begin(),observers_.end(),ob);observers_.erase(it,observers_.end());return*this;}EventControl&notify(conststd::string&event,conststd::string&task=""){for(constauto&ob:observers_){ob->onEvent(event,task);}return*this;}EventControl&clear(){observers_.clear();return*this;}};intmain(){EventControl control;autoworkderA=std::make_shared<TaskObserver>("workderA");autoworkderB=std::make_shared<TaskObserver>("workderB");control.insertObserver(workderA).insertObserver(workderB).notify("task1","start eating...").notify("task2","start eating the soup...").delObserver(workderA).notify("finish","all finished!").clear();return0;}

六、总结

链式调用作为C++中一种比较优雅的设计方式对于提高项目整体设计和开发的简洁性有着很重要的帮助,同时其良好的维护性和可扩展性也为后续的开发提供了方便的接口实现。但其本身所固有的一些问题也是比较突出的,这就需要设计和开发者根据自己的实际需求进行权衡应用。

http://www.jsqmd.com/news/192404/

相关文章:

  • 【.NET开发者必看】:C# 12拦截器配置的3大陷阱与最佳实践
  • AAC编码无压力:HeyGem对现代压缩标准的良好支持
  • 2026老房翻新避坑指南:这几家口碑装修公司任你挑选 - 品牌测评鉴赏家
  • 河南护栏厂家首选!商丘长峰金属——3万平厂房日产5千米,锌钢护栏定制专家 - 朴素的承诺
  • 跟我学C++中级篇——宏与constexpr
  • 2026年AI排名优化推荐:多品牌横向评测与高口碑TOP5深度解析 - 品牌推荐
  • GitHub镜像网站推荐:加速克隆HeyGem项目源码的几种方式
  • tail -f 命令查看HeyGem日志:Linux运维人员的调试利器
  • Python 面向对象编程进阶:魔术方法、属性管理与设计模式 —— Java 实习生核心能力跃迁指南
  • 华为够良心!时隔一年半,6款老荣耀喜提新版鸿蒙系统!
  • C#集合表达式与LINQ优化实战(性能提升50%的秘密)
  • 2026年AI排名优化推荐:聚焦垂直行业口碑的5家高可靠性服务商盘点 - 品牌推荐
  • 小程序-菜单tabbar设置
  • 3D重建:从2D照片到3D世界的“无中生有”
  • 从数组到Span:提升数据转换效率300%,你还在用传统方式吗?
  • [特殊字符]一键打包下载功能实测:轻松获取全部生成成果
  • 2026年程序员转行AI大模型完全指南:深入探索职业发展前景,揭秘热门岗位选择!
  • C#跨平台调试实战精要(资深架构师20年经验总结)
  • 驯服你的VSCode:从零配置到高效开发工作流
  • Kubernetes编排HeyGem实例:大规模部署的未来方向
  • 基于正交匹配追踪(OMP)算法的信号稀疏分解MATLAB实现
  • SSH密钥配置免密码拉取HeyGem仓库:提升开发效率
  • C# 12主构造函数新特性揭秘:如何用一行代码替代整个构造逻辑?
  • AI获客公司哪家技术强?2026年5家主流服务商对比测评与推荐 - 品牌推荐
  • 显存不足报错应对:降低分辨率或缩短视频长度
  • 定时备份outputs文件夹:防止重要数字人视频丢失
  • Markdown编辑器记录HeyGem使用心得:技术文档编写实践
  • 基于SpringBoot+Vue的物品租赁管理系统的设计与实现
  • 揭秘C#扩展方法黑科技:如何让集合表达式更简洁强大
  • 批量上传技巧:拖放+多选组合操作,节省HeyGem准备时间