1、不同类间的友元:
1)友元类;A类是B类的友元;A中所以的方法都可以访问B类的私有成员,在B类公有成员中声明添加friend class B;语句即可。
2)特定友元成员函数:A类中的特定成员函数是B类的友元;只有在B类中声明为其友元的A类成员函数才能访问B类的私有成员,在B类公有成员声明中添加:friend 函数返回值 A类名::函数原型;语句即可。此时由于在A类友元声明中用到了B类名、B类成员函数原型,因此A类的类声明必须位于B类之前,同时由于A类中该成员函数需要用到B类私有成员,若要将其作为内联函数,其函数定义必须位于A类声明之后,且需要添加inline关键字。
3)交互式友元类:A类(或者其中特定的方法)是B类的友元,同时B类(或特定的方法)是A类的友元;此时友元的声明同上述两条相同,但是需要在A、B类中同时进行友元声明,由于声明友元前编译器必须知道所声明的语句含义,因此需要用到前项声明,告知编译器相关信息,同时也必须注意,成员函数定义用到的信息必须在其之前定义。
4)共同友元:某一函数(或类)同时是A、B类的友元,函数可以是C类的成员函数,或者A(或者B)类的成员函数,注意其用到的信息必须在友元声明之前进行声明即可,可以采用前项声明、声明与定义分开等方式实现。
2、若A类(或函数)是B类的友元,友元的声明是在B类中而不是友元类中;若只是声明A类是B类的友元,A类的声明可以不在B类之前,因为友元类声明会指出A是一个类;若声明A类中的某个成员函数是B类的友元,A类的类声明必须位于B类之前,否则编译器无法识别友元函数。
3、不能使A类的部分成员是B类的友元,同时B类的部分成员是A类的友元;若A类的部分成员是B类的友元,也就意味着B类的声明必须在A声明之前,因为此时一个前项声明时不够的,因为它只能告诉编译器B是一个类而不能指出类成员的细节;同样,若B类的部分成员是A类的友元,A类的声明也必须位于B类前,因此这两者的同时实现是矛盾的。
4、异常:程序运行阶段的各种错误,可以通过调用系统自带的用于异常的函数,或者异常类处理异常。1)abort()函数:位于csdlib头文件中,调用该函数将终止程序;2)采用异常机制自定义异常处理过程:执行try块引发异常,throw返回异常(返回到与异常匹配的第一个try—cartch块,栈解退),cartch捕获异常;注意:基类异常对象可以捕获所有派生类异常对象,cartch捕获异常的顺序需要特别注意;3)exception类:头文件exception定义了exception异常类,可将其用作自定义异常类的基类,其包含一个const char*what()虚方法,返回一个字符串,可以在派生类中重新定义该方法,并使其返回异常类型名,当产生所定义的异常后可调用该方法,输出异常类型名;4)其他异常类:头文件stdexcept定义了logic_error,runtime_error类,且都是从exception公有派生而来,logic_error类的构造函数接受一个string对象,并将其作为what方法返回的字符串,若要从logic_error类派生自己的异常类,注意构造函数必须有参数,因为logic_error没有默认构造函数(具体见15.3注释);5)new头文件中的bad_alloc异常由exception公有派生而来,可用于使用new导致的内存分配问题;6)可以从一个异常类派生出另一个异常类,可以在类定义中嵌套异常类来组合异常,且这种嵌套声明本身可以被继承(以嵌套类所属类为基类的类可用该嵌套异常),还可以用作基类(嵌套异常类可用作其他类的基类)(详见程序清单15.14)。
5、RTTI(运行阶段类型识别):只适用于包含虚函数的类
1)、dynamic_cast运算符:用于确定某一指针指向的对象类型是否可以用于安全的转换为另一种类类型;语法1(使用指针):dynamic_cast<A*>(p2),若指针p2类型能被转换为A类型,则该表达式将返回p2对象的地址(可将其赋给一个A类指针),否则将返回一个空指针;语法2(使用引用):A&rs = dynamic_cast<A &>(rg),此时rg是对象的引用而不是指针,若该条语句请求成功rs将为rg的引用,若请求失败,将引发bad_cast异常(在头文件typeinfo中定义,有exception派生,可用try—catch块捕捉)。
2)、typeid运算符:用于确定两个对象是否为同一种类型,可以接受类名或者结果为对象的表达式作为参数,运算符返回一个对type_info(在有文件typeinfo中定义的一个类,重载了==和!=运算符,用于类之间类型的直接比较,还定义了一个name()方法,该方法返回一个字符串,一般为类名)对象的引用;语法:typeid(A)==typeid(*p),A为类名,p为指向类对象的指针,若p指向一个A类类型对象该表达式结果为true,否则为false;若p是一个空指针将引发bad_type异常(在typeinfo头文件中定义,由exception派生而来)
3)应尽量使用虚函数(根据指针所指对象的类型调用虚函数方法),其次为dynamic_cast,尽量避免使用typeid运算符。
6、类型转换运算符:dynamic_cast(类层次结构中进行向上转换),const_cast(只用于相同类型const与非const之间的转换,转换结果由接收参数定义决定),static_cast(只用于转换前后类型之间其中一个可隐式转换为另一个的情况),reinterpret_cast,强制类型转换并不做检查,除const_cast用于const与非const之间的转换外,其他类型转换要求转换前后的const性质一致,例如:不能用static_cast将基类const对象指针转换为非const派生类指针。