L53A08 第八章多态性( polymophism) 本章主要内容 1.多态的概念 2.虚函数 重点 3.静态绑定、动态绑定与动态绑定的实现机制 4.纯虚函数与抽象类 重点
21:53:08 第八章 多态性(polymophism) 本章主要内容 1. 多态的概念 2. 虚函数 —— 重点 3. 静态绑定、动态绑定与动态绑定的实现机制 4. 纯虚函数与抽象类 —— 重点
L53A08 §1多态的概念 多态性指一个名字,多种语义,或接口相同,多种实现 >C++支持两种形式的多态 1.静态多态(编译时多态) 2.动态多态(运行时多态)
21:53:08 §1 多态的概念 ➢多态性指一个名字,多种语义,或接口相同,多种实现 ➢C++支持两种形式的多态 1.静态多态(编译时多态) 2.动态多态(运行时多态)
L53A08 静态多态 >静态多态主要指函数和运算符的重载 例:函数的重载 int abs(int x(return x float abs(float x)( return x long abs(long x)( return x; j void maino cout < abs(-100)<< end1; cout <s abs(-2. 5f)<< end1 cout <s abs(123456789L)<< end1
21:53:08 ➢静态多态 ➢静态多态主要指函数和运算符的重载 例:函数的重载 int abs(int x){ return x; } float abs(float x){ return x; } long abs(long x){ return x; } void main() { cout << abs(-100) << endl; cout << abs(-2.5f ) << endl; cout << abs(123456789L) << endl; }
L53A08 例:函数的重载(续) class x public void Show(int char) void Show(char * char) void maino X Ob j xbj Show(1,'a) x0bj.Show(张三”,”b3);
21:53:08 例:函数的重载(续) class X{ public: void Show(int ,char); void Show(char *,char); }; void main() { X xObj; xObj.Show(1,’a’); xObj.Show(“张三” , ’b’); }
L53A08 例:函数重载(续) class x class Y: public X public public void show(int)( void showN void showo( void ma ino{|结论 X XOb j; 重载函数、运算符重载对应的函数 Y yob j; 的调用和函数体之间对应关系的建立 x0 bj Show0;是由编译程序和连接程序根据函数的参 y0 bj Show(10);数数目、参数类型的匹配关系,在编译 0 ojShow0;连接阶段完成的,所以静态多态又称为 y0bjx:$how0编译-连接时多态(简称编译时多态)
21:53:08 例:函数重载(续) class X { public: void show(){ } }; class Y:public X{ public: void show(int){ } void show(){ } }; void main(){ X xObj; Y yObj; xObj.Show(); yObj.Show(10); yObj.Show(); yObj.X::Show(); } 结论: 重载函数、运算符重载对应的函数 的调用和函数体之间对应关系的建立, 是由编译程序和连接程序根据函数的参 数数目、参数类型的匹配关系,在编译 连接阶段完成的,所以静态多态又称为 编译-连接时多态(简称编译时多态)
L53A08 动态多态 >与继承机制有关,建立在继承机制之上 >在继承机制中,能使用基类对象的地方就能用派生类对 象( upcast一向上转换) 例:. upcast(向上转换) 基类的指针可以指向派生类的对象,基类的引用可以引用 派生类的对象。导致编译时无法预知基类指针将来会指向 哪个派生类的对象,也无法预知基类的引用将来会引用哪 个派生类的对象 动态多态在继承机制之上靠虚成员函数实现 对虚函数的调用和函数体之间的对应关系不是在编译 连接阶段确定,而是在程序运行过程中动态的确定该函 数执行哪一个函数体,因此动态多态又称为运行时多态
21:53:08 ➢动态多态 ➢与继承机制有关,建立在继承机制之上 ➢在继承机制中,能使用基类对象的地方就能用派生类对 象(upcast — 向上转换) 例:.upcast(向上转换) ➢动态多态在继承机制之上靠虚成员函数实现 ➢对虚函数的调用和函数体之间的对应关系不是在编译、 连接阶段确定,而是在程序运行过程中动态的确定该函 数执行哪一个函数体,因此动态多态又称为运行时多态 基类的指针可以指向派生类的对象,基类的引用可以引用 派生类的对象。导致编译时无法预知基类指针将来会指向 哪个派生类的对象,也无法预知基类的引用将来会引用哪 个派生类的对象
L53A08 §2虚函数 虚函数是在基类中使用关键字 vir tua1进行声明,在派生 类中重新定义( override)的成员函数 例:虚函数 class x class Y: public x public public: vir tua 1 void fo vir tua l void fo cout<<“x::f0”; cout<<“Y∷:f0
21:53:08 §2 虚函数 ➢虚函数是在基类中使用关键字vir tual进行声明,在派生 类中重新定义(override)的成员函数 例:虚函数 class X { public: vir tual void f() { cout << “X::f()”; } }; class Y:public X { public: vir tual void f() { cout << “Y::f()”; } };
L53A08 虚函数的作用 能使用基类对象的地方就能使用派生类对象,故基类指针 可以指向派生类对象,基类引用也可以引用派生类对象 基类指针指向派生类对象,通过指针调用所指向对象中的 虚函数,C艹根据所指向对象的类型,在运行时确定调用 哪一个类的虚函数 基类引用引用派生类对象,通过引用调用所引用对象中的 虚函数,C艹根据所引用对象的类型,在运行时确定调用 哪一个类的虚函数 基类指针指向不同派生类的对象,基类引用引用不同派生 类的对象时,可以执行虚函数的不同版本
21:53:08 虚函数的作用 ➢能使用基类对象的地方就能使用派生类对象,故基类指针 可以指向派生类对象,基类引用也可以引用派生类对象 ➢基类指针指向派生类对象,通过指针调用所指向对象中的 虚函数,C++根据所指向对象的类型,在运行时确定调用 哪一个类的虚函数 ➢基类引用引用派生类对象,通过引用调用所引用对象中的 虚函数,C++根据所引用对象的类型,在运行时确定调用 哪一个类的虚函数 ➢基类指针指向不同派生类的对象,基类引用引用不同派生 类的对象时,可以执行虚函数的不同版本
例1:非虚成员函数 L53A08 class vehicle t public 引用基类对象,调引用派生类对象 void drive0用基类成员函数 调用基类成员函数 I cout dr 0; void maino( 指向派生类对象 vehicle yI car 调用基类成员函数 f(vh)if 别调用哪一个类中的 drive0? g(&V);g(&d;//分别调用哪一个类中的 dr ive0? vehicle *pVh pVh=&vh; pVh->drive o pVh=&c; pWh->dy r1 ve v
例 21:53:08 1:非虚成员函数 class vehicle{ public: void drive() { cout drive(); } void main(){ vehicle vh; car c; f(vh); f(c); //分别调用哪一个类中的drive()? g(&vh); g(&c); //分别调用哪一个类中的drive()? vehicle *pVh; pVh=&vh; pVh->drive(); pVh=&c; pVh->drive(); } 引用基类对象,调 用基类成员函数 引用派生类对象, 调用基类成员函数 指向基类对象,调 用基类成员函数 指向派生类对象, 调用基类成员函数
例1:虚成员函数 L53A08 class vehicle{引用基类对象,调引用派生类对象,调 public: 基类成员函数用派生类成员函数 vir tual void Ariveo I cout drive O void mino( 指向派生类对象,调 结论: 基类指针指向不同派生类的对象,基类引用引用不同派 生类的对象时,执行的是相应派生类中的虚函数
21:53:08 例1:虚成员函数 class vehicle{ public: vir tual void drive() { cout drive(); } void main(){ vehicle vh; car c; f(vh); f(c); //分别调用哪一个类中的drive()? g(&vh); g(&c); //分别调用哪一个类中的drive()? } 引用基类对象,调 用基类成员函数 引用派生类对象,调 用派生类成员函数 指向基类对象,调 用基类成员函数 指向派生类对象,调 用派生类成员函数 结论: 基类指针指向不同派生类的对象,基类引用引用不同派 生类的对象时,执行的是相应派生类中的虚函数