C++程序设计第八章
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第八章
多态性和虚函数
8.1多态性
静态联编所支持的多态性称为编译时的多态性。
动态联编所支持的多态性称为运行时的多态性,
8.1.1静态联编中的赋值兼容性及名字支配规律
8.1.2 动态联编的多态性
如果让编译器动态联编,也就是在编译“point*P=&c;”语句时,只根据兼容性规则检查它的合理性,也就是检查是否符合“派生类对象的地址可以赋给基类的指针”的条件。
至于“p->area()”
调用哪个函数,等程序运行到这里时再决定。
就要使类point的指针p指向派生类函数area的地址。
假设使用关键字virtual声明point的类area 函数,将这种函数称为虚函数。
当编译系统编译含有虚函数的类时,将为它建立以个虚函数表,表中的每个元素都指向一个虚函数地址。
编译器为类增加一个数据成员,这个数据成员是一个指向该虚函数表的指针,通常称为vptr。
虚函数的地址翻译取决于对象的内存地址。
编译器为含有虚函数的类的对象建立一个入口地址,这个地址用来存放指向虚函数表的指针vptr,然后按照类中的虚函数声明次序,一一填入函数指针。
派生类能继承基类的虚函数表,而且只要是和类同名(参数也相同)的成员函数,无论是否使用virtual 声明,它们都自动成为虚函数。
如果派生类没有改写基类的虚函数,则函数指针调用基类的虚函数。
如果派生改写了基类的函数,编译器将重新为派生类的虚函数建立地址,函数指针会调用改写过的虚函数。
虚函数的调用规则是:根据当前对象,优先调用对象本身的虚成员函数。
8.2 虚函数
一旦基类定义了虚函数该基类的派生类中的同名函数也自动成为虚函数。
8.2.1 虚函数
函数只能是类中的一个成员函数,但不能使静态成员,
8.2.2 虚函数实现多态的条件
关键字virtual指示C++编译器对调用虚函数进行动态联编。
这种多态性是程序运行到需要的语句处才动态确定的,所以称为运行时的多态。
(1)类之间的继承关系满足赋值兼容规则。
(2)改写同名虚函数
(3)根据赋值兼容性规则使用指针
满足钱联条件不一定产生动态编译,必须同时满足第3条才能保证实现动态编译。
第3友分为两种情况:第1中是已经演示过的按赋值兼容性规则使用基类指针(或引用)访问虚函数;第2种是把指针(或引用)作为函数参数,即这个函数不一定是类的成员函数,可以是普通函数,而且可以重载。
8.2.3构造函数和析构函数调用虚函数
在构造函数和析构函数中调用虚函数采用静态联编,
在建立类C的对象c时,它所包含的基类对象在派生类中定义的成员建立之前被建立。
在对象撤销时,该对象所包含的在派生类中定义的成员要先于基类对象之前撤销。
目前推存的C++标准不支持虚构函数。
有于析构函数不允许有参数,因此一个类只能有一个虚析构函数。
虚析构函数使用vitual说明。
Delete运算符合析构函数一起工作(new和构造函数一起工作),当使用delete删除一个对象时,delete 隐含着对析构函数的一次调用,如果析构函数为虚函数,则这个调用采用动态联编。
8.2.4纯虚函数与抽象
Virtual 函数类型函数名(参数列表)=0;
一个类可以说明多个纯虚函数,包含有纯虚函数的类称为抽象类。
如果通过同一个基类派生一系列的类,则将这些类总称为类族。
抽象至少含有一个虚函数,而且至少有一个虚函数是纯虚函数,
8.3 多重继承于虚函数
8.4类成员函数的指针与多态
在派生类中,当一个指向某基类成员的指针向一个虚函数,并且通过指向对象的基类指针(或引用)访问这个虚函数时,仍发生多态性。