一、友元 1、友元 类并非只能拥有友元函数,也可以拥有友元类。友元类的所有方法都可以访问原始类的所有私有或者保护成员。 (1)友元类:将类作为友元 (2)友元函数:将类中某个特定的函数作为另一个类的友元。
class Tv { .... friend void Remote::set_num(Tv &,int); } //编译器要处理这条语句,为了避开循环依赖,必须使用前向声明。 class Tv; class Remote{ ... }; class Tv{ ....};友元函数在原始类中应只声明,将定义放在实际定义TV类之后。 内联函数的链接性是内部的,意味函数必须定义在使用函数的文件中。
2、其他友元关系 除了通过友元和类的组合形式,还可以让类彼此成为对方的友元来实现。
3、共同的友元 函数需要访问两个类的私有数据,可以是一个类的成员,同时是另一个类的友元。 但有时函数作为两个类的友元更合理。
二、嵌套类 将声明放在另一个类中,称为嵌套类(nested class ); 包含类的成员函数,可以创建和使用嵌套类的对象。
1、嵌套与包含的区别:
包含:将类对象作为另一个类的对象。 嵌套:定义一个新的自定义类型,该类仅在该嵌套类声明的类中有效。
2、嵌套类的访问权限。
声明位置 包含类 嵌套类 类外部(对象) private ok no no protected ok ok no public ok ok ok
三、异常 c++提供的处理运行阶段错误的强大而灵活的工具。
一般程序异常的结果 1、 程序崩溃调用abort()函数(直接终止程序) 2、某些全局变量(erron)返回错误原因。
C++异常处理机制 try(将可能引发异常的代码放在其中) throw(抛出异常) catch(捕获异常) 异常的类型可以是基本的内置类型,字符串、类对象。 没有匹配到异常,将直接调用abort()函数。
3、将对象用作异常类型 引发异常的函数传递一个对象 (1)可以使用不同的异常类型来区分不同的函数在不同的情况下的异常。 (2)对象可以携带异常信息
4、C++11摒弃了异常规范
5、栈解退 问题前提:try块没有直接调用引发异常的函数,而是调用了对引发异常的函数进行调用的函数。
在没有引发异常的情况下,函数调用结束后,使用return返回调用的函数,释放存放在栈空间的内存, 多层函数调用情况也是如此。 在引发异常的情况下,函数不会返回上一级调用的函数,而是继续释放返回的地址,直到在栈空间找到一个 try块的中的返回地址,将控制权转到块尾的异常处理函数中,这就是栈解退。如果没有栈解退,对于中间的调用函数放在栈中的自动类对象其析构函数函数都不会被调用。
6、其他异常特性 (1)throw语句将程序的控制权返回到能够捕获异常的try-catch的结构组合中。 (2)如果有一个异常类继承的结构,应将类异常的catch放在最下面。 (3)catch(…)能够捕获任何异常 (4)new失败后返回空指针。
7、异常、继承和嵌套 (1)可以从一个异常类中派生另一个。 (2)可以在中定义嵌套异常类来组合。 (3)这种嵌套类本身可以被继承,但不可作为基类。
8、异常的迷失方向 (1)意外异常 (2)未捕获异常
四、RTTI(运行阶段类型识别) C++支持RTTI的元素,RTTI的只适用于包含虚函数的类,在这种情况下,才应该将派生类的指针赋值给基类指针。
1、dynamic_cast
dynamic_cast<Tyep *>pt; // 使基类指针转换为派生类的指针,通过判别指针的类型,从而确定调用的函数;2、typeid运行符和type-info的类 typeid使确定两个对象的是否为同种类型,接受两种参数 (1)类名 (2)结果为对象的表达式
typeid().name()返回类名。