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

【经典书籍】C++ Primer 第18章如何设计一个“好用、好看、好改”的函数精华讲解

 

「通俗易懂」地讲解《C++ Primer 第18章》,没问题!咱们就来一场零压力、无术语轰炸、一听就懂的技术课:

真正理解第18章在讲什么

明白这些知识在现实中有什么用

学会如何写出更好用的函数


📘 第18章标题:

《如何设计一个“好用、好看、好改”的函数?》

副标题:从“能跑就行”到“优雅高效”,你的函数还有很大进步空间!


🧠 一、这一章到底在讲啥?(一句话概括)

C++ Primer 第18 章,讲的是如何设计出更好、更清晰、更易用、更易维护的函数。

不是教你“怎么写函数”(比如怎么写 return、怎么传参数,这些你早就会了!),而是教你:

怎么把函数写得更好:更清晰、更专注、更易读、更易用、更易扩展。


🎯 二、为什么要学这一章?(现实意义)

想象一下:

  • 你写了个函数,名字叫 handle(),别人看了不知道它干嘛的

  • 你的函数很长,300 行,啥都干:计算、打印、保存文件、改全局变量

  • 你的函数参数有 6 个,调用时要写:func(a, b, c, d, e, f),看一眼就晕

  • 你的函数有时候返回 int,有时候返回 bool,有时候什么都不返回,调用方一头雾水

👉 这样的函数,自己改起来害怕,别人看了一脸懵,团队协作就是灾难!

第18章,就是来帮你解决这些“函数写得烂”的问题的!


🧩 三、第18章核心内容(通俗版逐个讲)

咱们把这一章的核心内容分成几个简单易懂的重点,一个一个来 👇


✅ 1. 函数要短小精悍(别写太长!)

🎯 一句话:

一个函数最好别超过 20 行,理想是 5~10 行,越短小、越清晰越好!

❌ 你可能犯的错:

  • 一个函数写了 300 行,又计算、又打印、又保存文件、又调接口

  • 嵌套了好几层 if-else,缩进比长城还高

✅ 你应该:

  • 一个函数只做一件事,比如:

    • 一个函数只计算价格

    • 一个函数只打印发票

    • 一个函数只保存数据

🎯 函数短小 = 好读、好改、好测试、好复用!


✅ 2. 函数要只做一件事(单一职责原则)

🎯 一句话:

一个函数只干一个任务,不要试图让它“包揽全局”。

❌ 写法(糟糕):

void processOrder() {// 1. 计算价格// 2. 打印小票// 3. 保存订单到数据库// 4. 发送邮件通知
}

✅ 写法(优雅):

int calculateTotal();       // 只算钱
void printReceipt();        // 只打小票
void saveOrder();           // 只存数据库
void sendNotification();    // 只发通知

🎯 职责单一 = 逻辑清晰 = 改起来不慌 = 团队协作友好!


✅ 3. 函数命名要清晰有意义(别用 handle / doSomething)

🎯 一句话:

函数名要一看就知道它在干嘛,别让别人去猜!

❌ 糟糕命名:

  • handle() → 处理啥?

  • processData() → 处理啥数据?

  • doSomething() → 干啥了?

✅ 好命名:

  • calculateTotalPrice()

  • validateUserInput()

  • saveToFile()

  • sendWelcomeEmail()

🎯 好名字 = 自解释,不用写一大堆注释!


✅ 4. 函数参数要少而精(别搞一大堆)

🎯 一句话:

函数参数最好不要超过 3 个,多了别人记不住、看不懂、用起来痛苦!

❌ 糟糕写法:

void setup(int a, int b, string c, bool d, float e, char f);

👉 调用时谁记得住顺序???

✅ 好写法:

  • 如果参数太多 → 用一个结构体 / 类来封装!

  • 输入参数尽量用 const T&(避免拷贝)

  • 避免一堆布尔 flag 参数(比如 bool isSave, bool isSend...)

🎯 参数少 = 调用简单 = 接口清晰 = 不容易出错!


✅ 5. 避免副作用(别偷偷改全局变量!)

🎯 一句话:

函数名没说会修改某个值,那就别改!尤其是全局变量!

❌ 潜在 bug:

  • 函数看起来只是“计算”,却偷偷改了某个全局状态

  • 函数返回 void,却修改了传进去的参数(除非你明确要说清楚)

✅ 你应该:

  • 函数的行为要“透明”:通过函数名、参数、返回值就能知道它做了什么

  • 不要让函数有“隐藏行为”,比如修改外部变量、依赖全局状态

🎯 无副作用 = 更安全、更可测、更靠谱!


✅ 6. 返回值要明确(别返回类型变来变去)

🎯 一句话:

一个函数最好始终返回同一种类型,比如总是返回 int,或者总是返回 bool,别一会儿返回这个,一会儿返回那个!

❌ 混乱写法:

  • 有时候返回 int(比如价格)

  • 有时候返回 bool(比如是否成功)

  • 有时候返回 string(比如消息)

  • 有时候什么都不返回(void)

✅ 好做法:

  • 明确返回值用途

    • 返回计算结果 → 比如 int / double

    • 返回操作状态 → 比如 bool(成功/失败)

    • 返回对象数据 → 比如 User / Order

🎯 返回值清晰 = 调用方放心 = 代码可读性强!


✅ 7. 函数逻辑要扁平,避免嵌套太深(别写迷宫代码)

🎯 一句话:

如果你的函数里有 5~6 层 if-else 或者 for 循环嵌套,那你就该考虑重构了!

❌ 写法(难读):

if (a) {if (b) {if (c) {// 好多代码...}}
}

✅ 你应该:

  • 提取函数,把一部分逻辑抽出去

  • 减少嵌套层级,让代码更扁、更清晰

  • 优先使用 return 提前退出,减少嵌套判断

🎯 逻辑扁平 = 代码清晰 = 容易理解 = 不容易出错!


🎁 四、总结:第18章教你写出什么样的函数?

好函数的特点说明你做到了吗?
✅ 短小精悍不超过 20 行,最好 5~10 行函数别写成小说
✅ 只做一件事功能单一,逻辑清晰不要又算又存又打印
✅ 命名清晰函数名表达意图,比如 calculateTotal()别用 handle / doSomething
✅ 参数要少最好不超过 3 个,复杂输入用结构体别让用户记参数顺序
✅ 无副作用不偷改全局变量,行为透明别让函数“背地里搞事情”
✅ 返回值明确返回类型稳定,调用方一看就懂不要返回类型变来变去
✅ 逻辑扁平避免多层嵌套 if/for,代码更清晰嵌套太多像迷宫,谁都怕

🚀 五、学完第18章,你成为了:

称号说明
函数设计高手你懂得如何设计职责清晰、接口友好的函数
代码可读性专家你的函数别人一读就懂,一用就会
团队协作达人你的函数别人调得爽、改得动、接得稳
优雅代码的代言人你写的函数,连你自己都忍不住想夸!

🎯 六、你接下来可以:

  • 回头看看你项目里的函数,有没有又臭又长的,拆一拆!

  • 给你的函数起个清晰、有意义的好名字

  • 控制函数参数数量,复杂输入用结构体封装

  • 避免函数有副作用,保持行为透明

  • 继续学习:函数重载、默认参数、Lambda、模板函数等高级技巧


你已经掌握了 C++ Primer 第18章的精华:如何设计出真正“好用、好看、好改”的函数,这是每个优秀程序员的必备技能!

太棒了!🎉「生动形象、幽默风趣、全面系统」地讲解《C++ Primer 第18章》,咱们这回要聊的是:


📚 第十八章标题(欢乐故事版):

《函数的自我修养:从“能跑”到“优雅”,小 C 的函数修炼之路》

副标题:如何设计一个让人用了都说“舒服”、调了都说“爽”的函数?


🎯 一句话定位:

C++ Primer 第18 章,讲的是“函数的设计哲学”:如何让你的函数写得更好看、更好用、更好调、更好维护,最终成为团队里人见人夸的“优雅函数”。


换句话说:这一章不教你“怎么写函数”(你早就会了),而是教你“怎么写好函数”!


🎭 一、开篇故事:小 C 的函数“黑历史”

我们的主角小 C,已经会写函数了,比如:

int add(int a, int b) {return a + b;
}

看起来没问题对吧?能跑!

但最近他写的函数,被团队吐槽惨了:


❌ 小 C 函数的黑历史:

  1. 函数名字叫 handle()processData()doSomething()

    → 听起来很厉害,但没人知道它到底干了啥!

  2. 一个函数 300 行,啥都干:计算、打印、保存文件、调接口、改全局变量

    “函数界的大杂烩”,没人敢动,改一行怕崩一片。

  3. 参数有 8 个!

    → 调用时像在排兵布阵:func(a, b, c, d, e, f, g, h),看一眼就晕!

  4. 函数返回值?有时候返回 int,有时候返回 bool,有时候返回 string,有时候什么都不返回!

    → 调用方:???你到底想干嘛?

  5. 函数内部逻辑嵌套 5 层 if-else,缩进比长城还高

    → 看代码像走迷宫,进去就出不来。


就在这时,一位代码高手出现了,他拍拍小 C 的肩膀说:

“函数写得好不好,不在能不能运行,而在好不好用、好不好读、好不好改、好不好扩展。你得修炼函数的‘自我修养’!”

于是,小 C 打开了《C++ Primer 第18章》……


🧠 二、第18章核心内容(通俗幽默版讲解)

这一章主要讲的是:如何设计出“优雅、清晰、可维护、可扩展”的函数,包括以下核心主题:


🎯 一句话总结:

“写函数不只是为了实现功能,而是为了让别人(和未来的你)用得爽、改得动、看得懂。”


✅ 1. 函数设计的基本原则(好函数的自我修养)

原则说明为什么重要
函数要短小精悍最好不超过 20 行,理想是 5~10 行像写短句,别写长篇小说,易读易维护
函数只做一件事(单一职责)不要又计算又打印又保存文件职责清晰,逻辑简单,改起来不慌
函数命名要清晰有意义不要叫 handle(),而要叫 calculateTotalPrice()好名字 = 自解释,不用猜
函数参数要少而精参数最好不要超过 3 个,多了难懂难用少即是多,清晰至上
避免副作用(Side Effect)函数名没说会改全局变量,那就别改!不要偷偷摸摸搞事情,容易出bug
返回值要明确不要一会儿返回 int,一会儿返回 bool,逻辑要一致调用方:我到底该拿啥?

✅ 2. 函数参数的设计(少即是多,清晰最重要)

场景好做法糟糕做法
参数太多(比如 5~8 个)考虑用结构体 / 类封装参数直接写 func(a,b,c,d,e,f,g,h) → 看着都晕
参数是配置项、选项结构体、枚举、bool 标志位要谨慎一堆 flag 参数 → 谁记得哪个是干嘛的?
输入 vs 输出参数输入用 const T&,输出考虑用返回值或引用参数不要乱改传进来的变量,除非你明确要说清楚

函数参数是函数的“接口”,设计得好,调用方用得爽;设计得烂,调用方想骂人!


✅ 3. 返回值设计(明确、一致、合理)

好的返回值设计说明
返回计算结果比如 int getPrice() 返回价格
返回状态 / 是否成功比如 bool saveToFile() 返回是否保存成功
返回对象 / 数据比如 User getUserById(int id)
避免返回多个不同类型不要一会儿返回 int,一会儿返回 string,逻辑混乱

返回值是函数的“输出口”,要让调用者一看就明白:“我拿到的到底是什么?”


✅ 4. 函数应该只做一件事(Single Responsibility Principle)

一个函数只做一件事情,并且把它做好!

比如:

❌ 烂函数:

void processOrder() {// 1. 计算总价// 2. 打印发票// 3. 保存到数据库// 4. 发送邮件通知
}

✅ 好函数拆法:

int calculateTotal();
void printInvoice();
void saveOrder();
void sendNotification();

每个函数只干一件事,逻辑清晰,调用灵活,改起来不害怕!


✅ 5. 避免过长函数 & 深层嵌套(可读性杀手!)

问题说明解决方案
函数太长(比如 300 行)看起来像小说,没人想读拆成多个小函数
嵌套 if/for 太深(比如 5~6 层)像迷宫,看代码像走迷宫提取函数,减少嵌套层级
逻辑分支太多一堆 if-else 或 switch-case考虑用策略模式、表驱动、或拆函数

代码的可读性 = 扁平化 + 清晰的逻辑层次


✅ 6. 函数的“签名”很重要(函数名 + 参数 + 返回值)

函数就像一扇门,函数签名就是门牌号 + 使用说明

一个好的函数签名应该让调用者一看就明白:

  • 这个函数是干嘛的?(函数名)

  • 我要传哪些东西进去?(参数)

  • 我能拿到什么结果?(返回值)

好的签名 = 好的沟通,好的设计 = 好的协作!


🎨 三、第18章 · 知识点幽默总结表(一图胜千言)

原则说明一句话
函数要短小最好不超过 20 行像写短诗,别写小说
函数只做一件事不要又计算又打印又保存职责单一,清晰易懂
命名要清晰不要叫 handle(),要叫 calculateTax()好名字是最好的注释
参数要少最好不超过 3 个少即是多,清晰优先
避免副作用别偷偷改全局变量函数名没说改,就不要改
返回值要明确不要返回类型变来变去调用方:我要拿啥?
逻辑要扁平避免嵌套太深、分支太多看代码像看书,不是走迷宫

🎭 四、小 C 的顿悟:从“能用就行”到“优雅高手”

经过高手指点,小 C 痛定思痛,决定重构他的函数:

  • 他把一个 300 行的大函数拆成了 7 个小函数,每个只做一件事

  • 他给函数起名不再用 doSomething(),而是 calculateDiscount()sendConfirmationEmail()

  • 他把参数从 8 个减到了 2 个,用结构体封装配置

  • 他避免了修改全局状态,函数变得纯净可测

结果?他的代码被团队评为“优雅典范”,连产品经理都忍不住点👍!


📌 五、学完第18章,你成为了:

称号说明
函数设计高手你懂得如何设计职责清晰、接口明确的函数
代码可读性专家你的函数让人一读就懂,一用就会
团队协作达人你的函数别人调得爽、改得动、接得稳
优雅代码的代言人你写的函数,连你自己都忍不住想夸!

🚀 六、你接下来可以:

  • 重构你项目中的“大杂烩函数”,拆成小而美的函数

  • 给你的函数起一个清晰、有意义的名字

  • 控制函数参数数量,用结构体封装复杂输入

  • 避免函数副作用,让函数更加纯净可靠

  • 继续学习:函数重载、默认参数、内联函数、lambda 表达式等高级函数特性


🎁 总结一句话(大实话):

**函数是 C++ 程序的基本组成单位,写函数不只是为了实现功能,更是为了沟通、协作、维护和扩展。

第18章教会你的,正是如何写出“别人喜欢用、自己喜欢改、团队喜欢看”的优雅函数。**


🔥 掌握了 C++ Primer 第18章的精华:从函数设计原则到参数返回值技巧,从代码风格到工程实践,一站式提升你的“函数修养”!

太棒了!

我决定采用一种你绝对喜欢的方式:


📜 第X回(章回体风格)

《小 C 闯关记:函数重载显神通,Lambda 妙笔生花,模板函数定乾坤!》

副标题:当你的函数不止一种写法,当你的代码可以“就地匿名”,当你的逻辑能适应任何类型——恭喜你,打开了 C++ 函数的高级副本!


🎭 本回主角: 小 C,一个已经会写普通函数的 C++ 程序员,但最近总听说:

  • “某某用了函数重载,代码简洁又直观!”

  • “某某写了个 Lambda,几行搞定回调,帅炸了!”

  • “某某用模板函数,一个逻辑支持 N 种类型,牛逼坏了!”

小 C 决定:闯关升级,解锁函数世界的隐藏技能!


第一关:函数重载(Overload)—— 一个名字,多种写法!


🎯 场景引入:

小 C 写了个函数,用来打印信息:

void print(int x) {cout << "整数: " << x << endl;
}

然后产品经理说:

“小 C 啊,我还想打印字符串、浮点数、甚至用户对象,你能不能……不用写一堆函数名,比如 printInt、printString、printDouble 啊?”

小 C 一脸懵:“啊?一个函数名,能干多个事儿?”

这时候,一位老程序员笑了:

“嘿嘿,C++ 支持函数重载同名函数,参数不同,编译器自动识别调用哪个!


✅ 什么是函数重载?

函数重载(Function Overload) 就是:你定义多个名字相同但参数列表不同的函数,在调用时根据传入参数的类型/个数,自动匹配调用哪一个。


✅ 示例代码:

void print(int x) {cout << "整数: " << x << endl;
}void print(double x) {cout << "浮点数: " << x << endl;
}void print(const string& s) {cout << "字符串: " << s << endl;
}

调用时:

print(10);           // 调用 print(int)
print(3.14);         // 调用 print(double)
print("Hello C++");  // 调用 print(const string&)

同一个函数名 print,根据你传的参数类型,自动选择对应的版本!


🎯 函数重载的关键:

要点说明
函数名相同都叫 print,或者叫 save、open,随你
参数列表不同参数类型、个数、顺序不同,比如 (int)、(double)、(int, string)
返回值类型不影响重载只有返回值不一样?不行!编译器认不出来!

❌ 错误示范:

int func()double func() 不是重载,是冲突!


🎨 漫画比喻 🎨:

想象函数就像一家餐厅的招牌菜:“秘制炒饭”

  • 有人点“炒饭(默认)” → 基础版

  • 有人点“炒饭 + 蛋” → 加蛋版

  • 有人点“炒饭 + 肉 + 青菜” → 豪华版

同一个名字(炒饭),不同配料(参数),但都是炒饭!

函数重载,就是同一名字,不同搭配,自动匹配!


第二关:Lambda 表达式 —— 匿名函数,就地编写,灵活如风!


🎯 场景引入:

小 C 写代码时,经常遇到一些“一次性小逻辑”,比如:

  • 给 vector 排序,按某个规则

  • 在算法里传个比较函数

  • 做个回调、事件触发、线程任务

以前他都是这么写:

bool compare(int a, int b) {return a > b;
}
sort(nums.begin(), nums.end(), compare);

但后来他发现,这个 compare 函数就只用了一次!写个命名函数太麻烦,还污染命名空间!

这时候,一位高手对他说:

“嘿嘿,你该用 Lambda 表达式匿名函数,就地定义,随用随写!


✅ 什么是 Lambda?

Lambda 表达式 是 C++11 引入的一种匿名函数,可以在代码里直接定义、就地使用,特别适合一次性、局部的小逻辑


✅ 基本语法:

[捕获](参数) -> 返回类型 { 函数体 }

大多数时候,返回类型可以自动推导,可以省略!


✅ 示例代码(排序为例):

vector<int> nums = {3, 1, 4, 1, 5};// 用 Lambda 表达式定义“从大到小排序”
sort(nums.begin(), nums.end(), [](int a, int b) {return a > b;
});

没有函数名、没有提前声明,直接在 sort 里写逻辑!


🎯 Lambda 的常见用法:

场景说明示例
排序规则给 sort 传比较逻辑[](int a, int b){ return a > b; }
线程任务给线程传任务函数thread t([](){ cout << "Hello from thread!" << endl; });
STL 算法比如 find_if、transform、for_each传入自定义操作
回调函数比如按钮点击、事件响应GUI 或异步逻辑常用

🎨 漫画比喻 🎨:

想象 Lambda 就像“街头暗号”或“一次性便签”

  • 你不需要给它起名字(比如“函数A”)

  • 你只需要在用到的地方,随手写一段逻辑,马上执行

  • 用完就丢,不占地方,不污染全局,灵活得一批!


第三关:模板函数(泛型函数)—— 一个逻辑,N 种类型!


🎯 场景引入:

小 C 写了个函数,用来返回两个数中较大的那个

int max(int a, int b) {return a > b ? a : b;
}

然后产品经理说:

“小 C 啊,我还想比两个 double、两个 string、甚至两个自定义对象,你能不能……不用写 maxInt、maxDouble、maxString 啊?”

小 C 痛苦万分:“我难道要写 10 个 max 函数???”

这时候,一位模板大师出现了:

“嘿嘿,你该用 模板函数(Template Function)写一次,支持任意类型!


✅ 什么是模板函数?

模板函数,就是将函数中的类型参数化,让函数可以适用于多种数据类型,而不用为每种类型都写一遍!


✅ 示例代码:

template <typename T>
T max(T a, T b) {return a > b ? a : b;
}

调用时:

cout << max(3, 7);           // int
cout << max(3.14, 2.71);     // double
cout << max(string("A"), string("B")); // string

同一个函数逻辑,支持任意支持 > 操作的类型!


🎯 模板函数的关键:

要点说明
template <typename T>声明这是一个泛型(模板)函数,T 是占位类型
T 可以是任意类型只要该类型支持函数里用到的操作,比如 >、+、==
编译器自动实例化你调用时用什么类型,编译器就生成对应的函数版本

🎨 漫画比喻 🎨:

想象模板函数就像“万能模具”

  • 你定义一次模具(逻辑),它可以浇筑出 int 版、double 版、string 版……

  • 你不用为每种零件都开一次模!

  • 写一次,到处可用,这就是泛型的力量!


🏆 三关通关总结:小 C 的函数神功大成!

技能作用适用场景你学会了啥
函数重载同一个函数名,不同参数,自动匹配打印、保存、计算等支持多类型输入一个名字,多种写法,代码更直观!
Lambda 表达式匿名函数,就地定义,灵活小巧排序、线程、回调、算法操作一次性逻辑,不用额外命名,写完就跑!
模板函数逻辑泛型化,支持任意类型比较、计算、工具函数一个函数,N种类型,写一次用万年!

🎁 终极收获:小 C 的感悟

“原来函数不只是‘实现功能的黑盒子’,它们还可以:

  • 有多种面孔(重载)

  • 有匿名身份(Lambda)

  • 有超能力(泛型模板)

这才是 C++ 函数的完全体啊!


🎉 现在,已经解锁了:

技能说明
函数重载让函数名更通用,调用更直观
Lambda 表达式让小逻辑更灵活,代码更紧凑
模板函数让逻辑支持任意类型,减少重复代码

 

 

http://www.dtcms.com/a/529248.html

相关文章:

  • Qt Creator:避免QRunnable和QObject多重继承
  • 抽奖机网站怎么做wordpress小工具是哪个文件夹
  • 简述网站推广的方法做一个app需要多少成本
  • JsonRpc框架介绍和环境搭建
  • 网站右下角悬浮窗口js代码 兼容各浏览器如何看还在建设的网站
  • qq浏览器收录网站提交入口wordpress 博客 视频
  • 关于宽带网络下公网地址的理解
  • 【面经】2025年软件测试面试题,精选100 道(附答案)
  • 网站风格优势网页设计哪里好
  • 案例研究_CVE-2018-1000517
  • 内存补丁技术:破解与防护的终极对决
  • 20251019状压DP总结
  • 西部数码网站管理助手v3.0产品设计ppt案例
  • 【2073】三角形面积
  • Datawhale秋训营-“大运河杯”数据开发应用创新大赛
  • 7(内存管理)(上)(了解)
  • 成都个人建网站ps软件下载电脑版免费怎么下载
  • 解析常见的限流算法
  • 潼南区做网站的公司中国医院建设协会网站
  • 夸克 × 大模型:从“搜索工具”到“智能体”的演化逻辑
  • 网站正在建设中色综合网页程序开发工具
  • 个人怎么开网上超市福州百度seo
  • 笔试强训(八)
  • 山西品牌网站建设成品网站源码68w68游戏
  • Linux内核进程管理子系统有什么第六十八回 —— 进程主结构详解(64)
  • 做网站需要商标注册吗阿里巴巴怎么做企业网站
  • 做视频网站需要哪些技术指标wordpress可以放视频吗
  • 动态库的使用-openssl
  • Maven 项目和 Maven Web 项目的异同点
  • Maven整理