C++启蒙课程:第8章  函数探幽

我们将为函数模块安装“超级外挂”和“智能升级”,让程序跑得更快、用起来更灵活!

⚡️

函数加速器与替身

掌握“瞬移”的 `inline` 魔法和变量的“分身术” `&` (引用)。

🛠️

智能客服与多功能工具

学习“贴心”的默认参数和“同名异能”的函数重载。

🌀

万能蓝图:函数模板

掌握“可变类型”的万能工厂蓝图 `template`,实现通用编程。

课时一:函数加速器与替身魔法

(覆盖知识点 8.1 - 8.2.7)

8.1 “瞬移”的内联魔法

常规函数调用像“坐飞机”(有开销),`inline` 函数像“瞬移”,代码被直接嵌入,速度更快。

(点击按钮查看)
// 8.1 必须在定义前加上 inline inline double square(double x) { return x * x; } // 编译器会尝试将其替换为: // result = x * x;

8.2.1 “变量的分身术” (引用)

引用(&)是变量的“别名”。它们是贴在同一个内存盒子上的两个不同名字,操作任意一个都会改变盒子里的值。

rats rodents
10
int rats = 10; // 8.2.1 rodents 成为 rats 的别名 int& rodents = rats; rodents++; // rodents 变为 11 // rats 也变为 11 cout << rats; // 输出 11

8.2.2 引用参数 (按引用传递)

“按值传递”只操作副本,“按引用传递” (使用 &) 被授权操作**原始数据**。

Original Wallet:
300
// 按值 (不可行, a, b 是副本) void swapv(int a, int b) { ... } // 8.2.2 按引用 (可行, a, b 是别名) void swapr(int& a, int& b) { int temp = a; a = b; b = temp; }

8.2.3 `const` 引用与临时变量

当 `const` 引用类型不匹配时,C++会创建“安全中转站”(临时变量)来保护原始数据。

// 8.2.3 const 引用 void show(const int& x) { cout << x; } int main() { double val = 5.5; // val 是 double, x 是 const int& // C++ 创建一个 int 临时变量(值为5) // x 成为该临时变量的别名 show(val); // 输出 5 }

课时二:智能客服与多功能工具

(覆盖知识点 8.3, 8.4, 8.2.4)

8.3 “贴心”的默认参数

默认参数允许你省略参数,函数会自动补上“智能客服”预设好的默认值。必须从右向左设置。

// 8.3 m=10, k=0 是默认参数 // 必须从右向左设置 void show(int n, int m=10, int k=0); // 调用: show(5); // n=5, m=10, k=0 show(5, 20); // n=5, m=20, k=0

8.4 “同名异能”工具箱 (重载)

函数重载允许你创建多个同名函数,只要它们的“特征标”(参数列表)不同。编译器会自动选择正确的工具。

// 8.4 同名异能工具箱 // 特征标: (int) void print(int n) { ... } // 特征标: (double) void print(double d) { ... } // 特征标: (string) void print(string s) { ... }

8.2.4 高效传递“大包裹”

传递大型结构或 `string` 时,按值传递(复制)很慢。使用 `const` 引用 (const&) 既能避免复制,又能保证安全。

// 慢: 复制整个大结构 void display(Stock s); // 8.2.4 快: 只传递地址, 且安全 void display(const Stock& s); // 8.2.5 同样适用于 string void show(const string& s);

课时三:万能蓝图:函数模板

(覆盖知识点 8.5.1 - 8.5.6)

8.5 “万能工厂蓝图” (Template)

模板 (template) 是一张“万能蓝图”,它使用泛型 `T`。当你需要时,编译器会根据 `T` (如 `int` 或 `double`) 自动“实例化”一个具体的函数。

// 8.5 万能蓝图 template // T 是一个泛型 void Swap(T& a, T& b) { T temp = a; a = b; b = temp; } // 编译器会根据调用自动生成: // void Swap(int&, int&); // void Swap(double&, double&);

8.5.5 “优先级警长” (重载解析)

当多个函数都能匹配时,“警长”会按优先级选择:1. 完全匹配 > 2. 提升转换 > 3. 标准转换。常规函数优先于模板。

1. void func(int) (完全匹配)
2. void func(long) (提升转换)
3. template void func(T) (模板)
void func(int n); // 候选 1 void func(long n); // 候选 2 template void func(T t); // 候选 3 // 'A' 是 char // 1. 警长发现 func(int) (提升转换) // 2. 警长发现 func(long) (提升转换) // 3. 警长发现 func(char) (模板) // ... 规则复杂, 但 C++ 会选择最佳匹配 func('A');

编程实践与作业 (8.8)

是时候检验你作为“函数升级大师”的实力了!

练习 1:多功能交换 (8.8 练习 1)

任务:

编写一个程序,实现两个 `int` 变量的交换。使用三个函数:一个不可行的按值传递函数 `swapv()`,一个可行的按指针传递函数 `swapp()`,以及一个可行的按引用传递函数 `swapr()`。

点击查看参考答案
#include <iostream> using namespace std; // 8.2.2 按引用传递 (可行) // 8.1 建议使用内联 inline void swapr(int & a, int & b) { int temp = a; a = b; b = temp; } // 按指针传递 (可行) void swapp(int * p, int * q) { int temp = *p; *p = *q; *q = temp; } // 按值传递 (不可行, 交换副本) void swapv(int a, int b) { int temp = a; a = b; b = temp; } int main() { int w1 = 300, w2 = 450; cout << "初始: " << w1 << ", " << w2 << endl; swapv(w1, w2); cout << "按值交换后: " << w1 << ", " << w2 << " (失败)" << endl; swapr(w1, w2); cout << "按引用交换后: " << w1 << ", " << w2 << " (成功)" << endl; swapp(&w1, &w2); cout << "按指针交换后: " << w1 << ", " << w2 << " (成功)" << endl; return 0; }
练习 2:重载 left() (8.8 练习 3)

任务:

编写两个重载函数 `left()`。第一个接受 const string &int n (默认=1),返回前n个字符。第二个接受 long numint n (默认=1),返回该整数的前n位数字。

点击查看参考答案
#include <iostream> #include <string> using namespace std; // 8.4 重载 1: 字符串 // 8.2.5 使用 const 引用 // 8.3 使用默认参数 string left(const string & str, int n = 1) { if (n < 0) n = 0; if (n > str.size()) n = str.size(); return str.substr(0, n); } // 8.4 重载 2: 整数 long left(long num, int n = 1) { if (n <= 0) return 0; long temp = num; int digits = 1; while (temp /= 10) digits++; if (n >= digits) return num; for (int i = 0; i < (digits - n); i++) { num /= 10; } return num; } int main() { cout << left("Hello", 3) << endl; // Hel cout << left("Hello") << endl; // H cout << left(12345, 2) << endl; // 12 cout << left(12345) << endl; // 1 return 0; }
练习 3:模板 maxn() (8.8 练习 6)

任务:

编写一个函数模板 `maxn()`,它接受一个 `T` 类型元素的数组和 `int n` (数组大小),并返回数组中的最大元素。

点击查看参考答案
#include <iostream> using namespace std; // 8.5 定义函数模板 maxn template T maxn(T arr[], int n) { if (n <= 0) return T(); // 返回 T 的默认值 T max_val = arr[0]; // 假设第一个是最大值 for (int i = 1; i < n; i++) { if (arr[i] > max_val) { max_val = arr[i]; } } return max_val; } int main() { int i_arr[] = {10, 44, 2, 70, 5}; double d_arr[] = {2.3, 1.1, 8.9, 0.5}; // 自动实例化 int 版本 cout << "Int Max: " << maxn(i_arr, 5) << endl; // 自动实例化 double 版本 cout << "Double Max: " << maxn(d_arr, 4) << endl; return 0; }

本章知识点总结与复习 (8.6)

核心概念 解释/功能 关键用法/示例
内联函数 (Inline)编译器将函数代码嵌入调用位置,提高速度。inline int func() { ... }
引用 (Reference)已定义变量的别名,必须在声明时初始化。int & ref = var;
引用参数按引用传递,函数使用原始数据,效率高。void func(const Struct & s);
默认参数允许为参数提供默认值,必须从右向左设置。void func(int a, int b=0);
函数重载多个同名函数,但特征标(参数列表)不同。void print(int); void print(double);
函数模板通用函数描述,使用泛型 (T) 定义。template ...
重载解析编译器确定调用哪个函数的规则。常规函数 > 模板函数