友元
友元函数:
友元函数不是类的成员函数,但能够访问类的私有(private)成员和保护(protected)成员。友元函数定义在类的外部,但在类的定义中通过friend
关键字声明。友元函数可以是普通函数,也可以是其他类的成员函数。
友元类:
如果一个类B是另一个类A的友元,那么类B的所有成员函数都可以访问类A的私有成员和保护成员。友元关系是单向的,不是传递的,也不是交换的。
友元的使用场景:
友元通常用于重载操作符,以便能够访问类的私有数据成员。然而,过度使用友元可能会破坏封装性,因此应谨慎使用。
类并非只能拥有友元函数,也可以将类作为友元。
在这种情况下,友元类的所有方法都可以访问原始类的私有成员和保护成员。
另外也可以做更严格的限制,只将特定的成员函数指定为另一个类的友元。
哪些函数、成员函数或类为友元是由类定义的,而不能从外部强加友情。因此,尽管友元被授予从外部访问类的私有部分的权限,但它们并不与面向对象的编程思想相悖;相反,它们提高了公有接口的灵活性。
嵌套类
在C++中,可以将类声明放在另一个类中。在另一个类中声明的类被称为嵌套类,它通过提供新的类型类作用域来避免名称混乱。包含类的成员函数可以创建和使用被嵌套类的对象;而仅当声明位于公有部分,才能在包含类的外面时候用嵌套类,而且必须使用作用域解析运算符。
对类进行嵌套与包含并不同。包含意味着将类对象作为另一个类的成员,而对类进行嵌套不创建类成员,而是定义了一种类型,与该类型仅在包含嵌套类声明的类中有效。
定义与声明:
嵌套类是在另一个类的定义中声明的类。嵌套类的作用域被限制在其包含它的类的内部。嵌套类可以是公有(public)、私有(private)或保护(protected)的,这决定了它们如何被外部世界或派生类访问。
使用场景:
嵌套类常用于实现辅助类或仅与包含它的类紧密相关的类。它们有助于组织代码和隐藏实现细节,同时提供对包含类的成员的访问。
访问权限:
嵌套类的访问权限取决于其声明在包含类中的位置。公有嵌套类可以从包含类的外部访问,私有嵌套类则只能由包含类的成员函数和友元访问。
异常
下面介绍如何使用异常机制来处理错误。C++异常是对程序运行过程中发生的异常情况。异常提供了将控制权从程序的一个部分传递到另一个部分的途径。对异常的处理有3个组成部分:
引发异常;
使用处理程序捕获异常;
使用try块。
try块:
try块用于包含可能引发异常的代码。如果在try块中的代码执行过程中引发异常,程序控制将立即跳出try块,并查找匹配的catch块。
catch块:
catch块用于捕获和处理异常。每个catch块都指定它能够处理的异常类型。当异常被抛出时,控制流会跳转到第一个能够处理该异常类型的catch块。
throw语句:
throw语句用于显式地引发异常。它后面通常跟随一个值,该值描述了异常的特性。当throw语句被执行时,当前的函数执行会立即停止,异常开始传播。
异常的传播:
如果函数无法处理引发的异常,它会将该异常传播给调用它的函数。这个过程会沿着函数调用栈向上进行,直到找到能够处理该异常的catch块或程序终止。
异常的规格:
虽然C++11及之后的版本不再推荐使用异常规格来限制函数可能抛出的异常类型,但了解这一概念有助于理解C++的异常处理机制的历史演变。在旧版本的C++中,异常规格用于指定函数可能抛出的异常类型列表。
其他:
abort()函数用于立即终止程序的执行,不执行任何清理操作。它通常用于处理无法恢复的错误情况。
exit()函数也用于终止程序,但它允许程序执行清理操作(如全局对象的析构函数)。它可以接受一个整数值作为退出状态码。
总结
友元使得能够为类开发更灵活的接口。类可以将其他函数、其他类和其他类成员函数作为友元。在某些情况下,可能需要使用前向声明,需要特别注意类和方法声明的顺序,以正确的组合友元。
嵌套类是在其他类中声明的类,它有助于设计这样的助手类,即实现其他类,但不必是公有接口的组成部分。
C++异常机制为处理拙劣的编程时间,如不适当的值、I/O失败等,提供了一种灵活的方式。引发一场将终止当前执行的函数,将控制权传给匹配的catch块。catch块紧跟在try块的后面,为捕获异常,直接或间接导致异常的函数调用必须位于try块中。这样程序将执行catch块中的代码。这些代码试图解决问题或终止程序。类可以包含嵌套的异常类,嵌套异常类在相应的问题被发现时将被引发。函数可以包含异常规范,指出在该函数中可能引发的异常;但C++11摒弃了这项功能。未被捕获的异常(没有匹配的catch块的异常)在默认情况下将终止程序,意外异常(不与任何异常规范匹配的异常)也是如此。
RTTI(运行阶段类型信息)特性让程序能够检测对象的类型。dynamic_cast运算符用于将派生类指针转换为基类指针,其主要用途是确保可以安全地调用虚函数。typeid运算符返回一个tpye_info对象。可以对两个typeid的返回值进行比较,以确定对象是否为特定的类型,而返回的type_info对象可用于获得关于对象的信息。
与通用的转换机制相比,dynamic_cast, static_cast, const_cast和reinterpret_cast提供了更安全、更明确的类型转换。