第15章:友元、异常和其他
探索C++的高级特性:程序的“秘密伙伴”、错误处理的“防弹衣”与运行时的“身份扫描器”。
秘密伙伴:友元
学习如何通过友元(friend)打破封装,实现类与类之间的高效协作。
程序防弹衣:异常
掌握 try/catch 机制,优雅地处理程序运行时可能出现的各种错误。
身份扫描器:RTTI
了解如何在程序运行时识别对象的真实类型,实现更安全的动态操作。
环节一:友元的家族和嵌套类
有时候,我们需要给特定的类或函数一把“万能钥匙”,让它们能访问一个类的私有成员。
👨👩👧👦 友元类:家族特权
如果 B 类是 A 类的友元,那么 B 类的所有方法都能访问 A 类的私有成员。这就像给了整个家族进入私人花园的许可。
🔑 友元成员函数:点对点授权
更精确的授权!只让 B 类的某个特定方法成为 A 类的友元,就像只给一个人一把特定的门钥匙,而不是整个大门的钥匙。
🧰 嵌套类:随身工具箱
在一个类内部定义另一个类。这个“内部类”的作用域被限制在外部类中,有助于组织代码,避免命名冲突。
代码示例:友元授权
环节二:异常机制——错误的紧急处理
程序出错时怎么办?直接崩溃?不!我们可以用“异常”来优雅地处理问题。
除法计算器:异常演示
三要素:尝试、抛出、捕获
try (尝试): 将可能出错的代码包裹起来,像一个安全测试区。
throw (抛出): 当错误发生时,立刻“抛出”一个异常信号,中断正常流程。
catch (捕获): 准备一个“捕手”,专门接收特定类型的异常信号并处理它。
代码示例:处理除零错误
环节四:RTTI——运行时识别对象身份
当基类指针指向不同派生类对象时,我们如何知道它的“真实身份”?
身份扫描器:`dynamic_cast` 演示
指针
Animal* p
实际对象 1
🐱
Cat
实际对象 2
🐾
Animal
环节五:类型转换运算符的安全替代
告别粗暴的C风格强转,拥抱更安全、意图更明确的C++转换运算符。
static_cast
比喻:理性的转换。 用于良性的、编译时就能确定的转换,如 int 转 double。它是最常用的转换符。
dynamic_cast
比喻:多态转换。 专用于处理多态类型(有虚函数的类)的向下转换,进行运行时安全检查。
const_cast
比喻:删除只读锁。 唯一能移除变量 const 属性的转换符。使用时需格外小心,通常用于与旧API交互。
reinterpret_cast
比喻:危险的重新解释。 最不安全的转换,它仅仅是重新解释内存中的位模式。极少使用,通常用于底层编程。
环节六:总结与编程挑战
你已经掌握了C++的高级特性!现在来试试这些挑战任务吧。
练习 1:除法异常处理
任务:
编写一个函数 `div_safe(int a, int b)`。如果除数 `b` 为零,抛出一个整数 `(-1)` 作为异常。在 `main` 函数中,使用 `try/catch` 块捕获这个异常,并打印出错误信息。
点击查看参考答案
练习 2:多态与安全转换
任务:
- 定义基类 `Animal` (带虚函数) 和派生类 `Cat`。
- 编写函数 `process_animal(Animal* p)`,用 `dynamic_cast` 尝试将其转为 `Cat*`。如果成功,调用 `Cat` 的特有方法;如果失败,则调用基类方法。
- 在 `main` 中,用 `static_cast` 将 `int` 转换为 `double` 并进行除法运算,以演示其用途。