《计算机网络原理》第8章-多态性和虚函数-精选课件.pptx
《《计算机网络原理》第8章-多态性和虚函数-精选课件.pptx》由会员分享,可在线阅读,更多相关《《计算机网络原理》第8章-多态性和虚函数-精选课件.pptx(36页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、lC+支持两种多态性,即编译时的多态性和运行时的多支持两种多态性,即编译时的多态性和运行时的多态性。编译时的多态性通过使用重载函数或模板获得,运态性。编译时的多态性通过使用重载函数或模板获得,运行时的多态性通过使用继承和虚函数来获得。行时的多态性通过使用继承和虚函数来获得。l联编是描述编译器决定在程序运行时,一个函数调用应联编是描述编译器决定在程序运行时,一个函数调用应执行哪段代码的一个术语,是实现多态性的基础。执行哪段代码的一个术语,是实现多态性的基础。第第8章多态性和虚函数章多态性和虚函数第第8章多态性和虚函数章多态性和虚函数28.1多态性多态性8.1.1静态联编中的赋值兼容性和名字支配规
2、律静态联编中的赋值兼容性和名字支配规律类的对象和调用的函数一一对应,程序编译类的对象和调用的函数一一对应,程序编译时即可确定对象调用哪一个函数,称为静态时即可确定对象调用哪一个函数,称为静态联编联编通过指针调用成员函数时:通过指针调用成员函数时:所调用成员函数为指针所属类的成员函数所调用成员函数为指针所属类的成员函数即由赋值兼容规则决定指针调用的成员函数即由赋值兼容规则决定指针调用的成员函数348.1.2动态联编的多态性动态联编的多态性要实现程序运行时决定指针所调用的函数是基类要实现程序运行时决定指针所调用的函数是基类的还是派生类的,即:动态联编。的还是派生类的,即:动态联编。可利用虚函数实现
3、动态联编可利用虚函数实现动态联编 由此可见,对象的内存地址空间中只包含数据成员,并不由此可见,对象的内存地址空间中只包含数据成员,并不存储有关成员函数的信息。这些成员函数的地址翻译过程与存储有关成员函数的信息。这些成员函数的地址翻译过程与其对象的内存地址无关。编译器只根据数据类型翻译成员函其对象的内存地址无关。编译器只根据数据类型翻译成员函数的地址并判断调用的合法性。数的地址并判断调用的合法性。virtualdoublearea()return0.0;当编译系统编译含有虚函数的类时,为它建立当编译系统编译含有虚函数的类时,为它建立一个虚函数表,表中的每一个元素都指向一个虚函一个虚函数表,表中的
4、每一个元素都指向一个虚函数的地址。此外,编译器也为类增加一个数据成员,数的地址。此外,编译器也为类增加一个数据成员,这个数据成员是一个指向该虚函数表的指针,通常这个数据成员是一个指向该虚函数表的指针,通常称为称为vptr。如果派生类如果派生类Circle没有重写这个没有重写这个area虚函数,虚函数,则派生类的虚函数表里的元素所指向的地址就是基则派生类的虚函数表里的元素所指向的地址就是基类类Point的虚函数的虚函数area的地址,即派生类仅继承基类的地址,即派生类仅继承基类的虚函数,它调用的也是基类的的虚函数,它调用的也是基类的area函数。函数。现在将它改写如下:现在将它改写如下:virt
5、ualdoublearea()returnPI*radius*radius;这时,编译器也将派生类虚函数表里的元素指向这时,编译器也将派生类虚函数表里的元素指向Circle:area(),即指向派生类,即指向派生类area函数的地址。函数的地址。由此可见,虚函数的地址翻译取决于对象的内存地址。编译由此可见,虚函数的地址翻译取决于对象的内存地址。编译器为含有虚函数类的对象首先建立一个入口地址,这个地址用器为含有虚函数类的对象首先建立一个入口地址,这个地址用来存放指向虚函数表的指针来存放指向虚函数表的指针vptr,然后按照类中虚函数的声明次,然后按照类中虚函数的声明次序,一一填入函数指针。序,一一
6、填入函数指针。当调用虚函数时,先通过当调用虚函数时,先通过vptr找到虚函数表,然后再找出找到虚函数表,然后再找出虚函数的真正地址。虚函数的真正地址。l派生类能继承基类的虚函数表,而且只要是和基派生类能继承基类的虚函数表,而且只要是和基类同名的类同名的(参数也相同参数也相同)成员函数,无论是否使用成员函数,无论是否使用virtual声明,它们都自动成为虚函数。声明,它们都自动成为虚函数。l如果派生类没有改写继承基类的虚函数,则函数如果派生类没有改写继承基类的虚函数,则函数指针调用基类的虚函数。如果派生类改写了基类指针调用基类的虚函数。如果派生类改写了基类的虚函数,编译器将重新为派生类的虚函数建
7、立的虚函数,编译器将重新为派生类的虚函数建立地址,则函数指针调用这个改写过的虚函数。地址,则函数指针调用这个改写过的虚函数。98.2虚函数虚函数8.2.1 虚函数的定义虚函数的定义虚函数的格式:虚函数的格式:虚函数的格式:虚函数的格式:virtual double area()return 0;virtual double area()return 0;虚函数的调用规则:虚函数的调用规则:虚函数的调用规则:虚函数的调用规则:根据当前对象,优先调用对象本身的虚成员函数。根据当前对象,优先调用对象本身的虚成员函数。根据当前对象,优先调用对象本身的虚成员函数。根据当前对象,优先调用对象本身的虚成员函
8、数。虚函数是动态联编的,是在执行期间接调用实际上欲联编的虚函数是动态联编的,是在执行期间接调用实际上欲联编的虚函数是动态联编的,是在执行期间接调用实际上欲联编的虚函数是动态联编的,是在执行期间接调用实际上欲联编的函数。函数。函数。函数。一旦基类定义了虚函数,该基类的派生类中的同名函数一旦基类定义了虚函数,该基类的派生类中的同名函数一旦基类定义了虚函数,该基类的派生类中的同名函数一旦基类定义了虚函数,该基类的派生类中的同名函数也自动成为虚函数。也自动成为虚函数。也自动成为虚函数。也自动成为虚函数。虚函数不能是静态成员。虚函数不能是静态成员。虚函数不能是静态成员。虚函数不能是静态成员。108.2.
9、2虚函数实现多态性虚函数实现多态性使用虚函数产生多态的个前提:使用虚函数产生多态的个前提:使用虚函数产生多态的个前提:使用虚函数产生多态的个前提:、类之间的继承关系满足赋值兼容性规则;、类之间的继承关系满足赋值兼容性规则;、类之间的继承关系满足赋值兼容性规则;、类之间的继承关系满足赋值兼容性规则;、改写了同名虚函数;、改写了同名虚函数;、改写了同名虚函数;、改写了同名虚函数;、根据赋值兼容性规则使用指针(或引用)。、根据赋值兼容性规则使用指针(或引用)。、根据赋值兼容性规则使用指针(或引用)。、根据赋值兼容性规则使用指针(或引用)。其中前提分为两种情况:其中前提分为两种情况:其中前提分为两种情
10、况:其中前提分为两种情况:、按赋值兼容性规则使用基类指针(或引用)访问虚、按赋值兼容性规则使用基类指针(或引用)访问虚、按赋值兼容性规则使用基类指针(或引用)访问虚、按赋值兼容性规则使用基类指针(或引用)访问虚函数;函数;函数;函数;、把指针(或引用)作为函数参数,即这个函数不一、把指针(或引用)作为函数参数,即这个函数不一、把指针(或引用)作为函数参数,即这个函数不一、把指针(或引用)作为函数参数,即这个函数不一定是类的成员函数,可以是普通函数,而且可以重载。定是类的成员函数,可以是普通函数,而且可以重载。定是类的成员函数,可以是普通函数,而且可以重载。定是类的成员函数,可以是普通函数,而且
11、可以重载。【P171P171中的中的中的中的displaydisplay函数函数函数函数】【例例8.2】分别使用指针和引用的分别使用指针和引用的display函数。函数。分析下面程序的输出结果:分析下面程序的输出结果:#includeusingnamespacestd;constdoublePI=3.14159;classPointprivate:doublex,y;public:Point(doublei,doublej)x=i;y=j;virtualdoublearea()return0;classCircle:publicPointprivate:doubleradius;public:
12、Circle(doublea,doubleb,doubler):Point(a,b)radius=r;doublearea()returnPI*radius*radius;voiddisplay(Point*p)coutarea()endl;voiddisplay(Point&a)couta.area()endl;voidmain()Pointa(1.5,6.7);Circlec(1.5,6.7,2.5);Point*p=&c;Point&rc=c;display(a);display(p);/display(&c)display(rc);/display(c)程序输出如下:程序输出如下:01
13、9.634919.634914.构造函数和析构函数调用虚函数构造函数和析构函数调用虚函数重要规则:采用静态联编,即只调用自己的类或基类中重要规则:采用静态联编,即只调用自己的类或基类中重要规则:采用静态联编,即只调用自己的类或基类中重要规则:采用静态联编,即只调用自己的类或基类中定义的函数,但不是任何在派生类中重定义的虚函数。定义的函数,但不是任何在派生类中重定义的虚函数。定义的函数,但不是任何在派生类中重定义的虚函数。定义的函数,但不是任何在派生类中重定义的虚函数。P83P83newnew和构造函数和构造函数和构造函数和构造函数deletedelete和析构函数和析构函数和析构函数和析构函数
14、标准标准标准标准c+c+不支持虚构造函数不支持虚构造函数不支持虚构造函数不支持虚构造函数支持虚析构函数,如果基类的虚析构函数,则派生类的支持虚析构函数,如果基类的虚析构函数,则派生类的支持虚析构函数,如果基类的虚析构函数,则派生类的支持虚析构函数,如果基类的虚析构函数,则派生类的析构函数是否用析构函数是否用析构函数是否用析构函数是否用virtualvirtual说明,均为虚析构函数;如派生说明,均为虚析构函数;如派生说明,均为虚析构函数;如派生说明,均为虚析构函数;如派生类未定义析构函数,则编译器生成的也是虚析构函数。类未定义析构函数,则编译器生成的也是虚析构函数。类未定义析构函数,则编译器生
15、成的也是虚析构函数。类未定义析构函数,则编译器生成的也是虚析构函数。在构造函数和析构函数中调用虚函数时,采在构造函数和析构函数中调用虚函数时,采用静态联编,即它们所调用的虚函数是自己的类或用静态联编,即它们所调用的虚函数是自己的类或基类中定义的函数,但不是任何在派生类中重定义基类中定义的函数,但不是任何在派生类中重定义的虚函数。的虚函数。【例例8.3】在构造函数和析构函数中调用虚函数。在构造函数和析构函数中调用虚函数。#includeusingnamespacestd;classApublic:A()virtualvoidfunc()coutConstructingAendl;A()virtu
16、alvoidfund()coutDestructorAendl;classB:publicApublic:B()func();voidfun()coutComehereandgo.;func();B()fund();classC:publicBpublic:C()voidfunc()coutClassCendl;C()fund();voidfund()coutDestructorCendl;voidmain()Cc;c.fun();输出结果如下:输出结果如下:ConstructingA/建立对象建立对象c调用调用B()产生产生Comehereandgo.ClassC/c.fun()输出输出De
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机网络原理 计算机网络 原理 多态性 函数 精选 课件
限制150内