C++启蒙课程:第11章  使用类

我们将掌握“运算符重载”和“友元”这两项高级魔法,让我们的“智能对象”能执行加减乘除,像内置类型一样好用!

🛠️

多功能工具箱:成员重载

学习“多功能工具”机器人如何使用 `operator+` 来处理对象相加。

🎟️

VIP通行证:友元与输出

掌握 `friend`“VIP通行证”和 `operator<<` “信息管道”重载。

🔄

数据自动转换

学习“自动翻译机”(单参数构造函数)如何将数字自动转换为对象。

课时一:多功能工具箱:成员运算符重载

(覆盖知识点 11.1 - 11.2.3)

11.2.1 “多功能工具” (加法)

A = B + C 会被C++翻译为 A = B.operator+(C)。`B` 机器人(调用对象)拿起 `+` 扳手,把 `C`(参数)加到自己身上,返回一个新对象 `A`。

B (2h) 🤖 C (1h 30m)
class Time { public: // 11.2.1 重载 + 运算符 // B.operator+(C) Time operator+(const Time& t) const { Time sum; sum.minutes = minutes + t.minutes; sum.hours = hours + t.hours; // ... (处理进位) ... return sum; // 返回新对象 A } };

11.2.3 重载乘法 (*)

我们也可以重载 `*`,让对象能乘以一个 `double` 因子。

Time (1h 30m) 🤖 Factor (2.0)
// 11.2.3 重载 * 运算符 Time Time::operator*(double mult) const { double total_minutes = (hours * 60 + minutes) * mult; Time result; result.hours = int(total_minutes / 60); result.minutes = int(total_minutes) % 60; return result; }

课时二:VIP通行证:友元与输出重载

(覆盖知识点 11.3)

11.3 “私人会所”与“VIP信使”

`private` 数据是“私人会所”,只有“保安” (成员函数) 能进。`friend` 是“VIP信使”,被授予了特殊通行证。

私人会所
(private: double balance)
class Time { private: int hours; // 私人会所 public: void show(); // 保安 (成员) // 11.3.1 授予 VIP 通行证 friend void v_pass(Time & t); }; // VIP 信使 (非成员, 但可访问 private) void v_pass(Time & t) { t.hours = 10; // OK! }

11.3.2 “信息管道的链接” (<<)

重载 `<<` 必须是**友元** (因为 `cout` 在左边)。它必须返回 `ostream&` (管道引用),以实现链式输出。

Time t(7, 30);
cout « t « endl
// 11.3.2 operator<< 友元定义 ostream & operator<<(ostream & os, const Time & t) { // os 是 cout 的别名 // 可以访问 t 的私有成员 os << t.hours << " 小时, " << t.minutes << " 分钟"; // 11.3.2 返回 ostream 引用 return os; }

课时三:数据自动转换与高级应用

(覆盖知识点 11.6, 11.2.3)

11.6 “自动翻译机”

如果构造函数只接受一个参数,C++会把它当作“自动翻译机”,将参数类型 (如 `int`) 自动转换为类类型 (如 `Time`)。

100 (int) ?
class Time { public: // 11.6 单参数构造函数 // (自动翻译机) Time(int m) { hours = m / 60; minutes = m % 60; } }; // C++ 会自动将 100 翻译为 Time(100) Time t = 100;

高级应用:非成员重载

成员重载 `*` 只允许 `Time * 2.5`。非成员 (友元) 重载 `*` 则允许 `2.5 * Time`。

Time t(2, 0);
class Time { // 成员 (t * 2.5) Time operator*(double m) const; // 11.3.1 友元 (2.5 * t) friend Time operator*(double m, const Time & t); }; // 友元定义 Time operator*(double m, const Time & t) { return t * m; // 委托给成员函数 }

编程实践与作业

是时候检验你作为“高级魔法师”的实力了!

练习 1:时间相乘 (11.2.3)

任务:

Time 类编写 operator*() 成员函数,将 Time 对象乘以一个 double 因子,并返回一个新的 Time 对象。

点击查看参考答案
#include <iostream> // ... (Time 类声明) ... class Time { private: int hours; int minutes; public: Time(int h = 0, int m = 0) : hours(h), minutes(m) {} void show() const { std::cout << hours << "h, " << minutes << "m"; } // 11.2.3 重载乘法 Time operator*(double mult) const; }; Time Time::operator*(double mult) const { double total_minutes = (hours * 60 + minutes) * mult; Time result; result.hours = int(total_minutes / 60); result.minutes = int(total_minutes) % 60; return result; } // ... (main 函数测试) ...
练习 2:友元输出 (11.3.2)

任务:

Time 类重载 << 运算符,使其能够直接将时间对象输出到 cout,并支持链式输出。

点击查看参考答案
#include <iostream> using namespace std; class Time { private: int hours; int minutes; public: Time(int h = 0, int m = 0) : hours(h), minutes(m) {} // 11.3.1 友元函数声明 friend ostream & operator<<(ostream & os, const Time & t); }; // 11.3.2 非成员友元函数定义 ostream & operator<<(ostream & os, const Time & t) { os << t.hours << " 小时, " << t.minutes << " 分钟"; return os; // 11.3.2 返回 ostream 引用 } int main() { Time t(7, 30); cout << t << " (链式输出)" << endl; return 0; }
练习 3:自动转换与非成员重载 (11.6)

任务:

Time 类定义一个单参数构造函数 `Time(int m)` (分钟),并编写一个非成员 `operator*`,支持 double * Time 的操作。

点击查看参考答案
#include <iostream> using namespace std; class Time { private: int hours; int minutes; public: Time(int h = 0, int m = 0) : hours(h), minutes(m) {} // 11.6 单参数构造函数 Time(int m) { hours = m / 60; minutes = m % 60; } // (成员 operator* ... ) Time operator*(double m) const { /* ... */ return Time(0,0); } // 11.3.1 声明友元 friend Time operator*(double mult, const Time & t); friend ostream & operator<<(ostream & os, const Time & t); }; // 实现非成员重载 Time operator*(double mult, const Time & t) { return t * mult; // 委托给成员函数 } ostream & operator<<(ostream & os, const Time & t) { os << t.hours << "h, " << t.minutes << "m"; return os; } int main() { // 11.6 演示自动转换 Time t = 100; // 1h 40m cout << t << endl; // 演示非成员重载 Time t2 = 0.5 * t; cout << t2 << endl; return 0; }

本章知识点总结与复习

核心概念 解释/功能 关键用法/示例
运算符重载赋予C++运算符适用于类对象的新含义。T3 = T1 + T2;
重载函数名函数名格式为 `operator` 后面跟运算符。operator+(), operator<<()
重载限制不能创建新运算符;不能改变优先级;`=, (), [], ->` 必须是成员。sizeof, ., :: (不可重载)
友元 (Friend)授予非成员函数访问类私有数据的权限。friend void func(...);
`<<` 运算符重载必须定义为非成员函数(通常是友元)。friend ostream& operator<<(...)
链式输出`operator<<` 必须返回 `ostream &` 引用。return os;
类自动转换单参数构造函数可被用作自动类型转换函数。Time(int m); Time t = 60;