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 < "drive a generic vehicle < end1; J class car: public vehicle t 指向基类对象,调 public 用基类成员函数 oid drive icout < "df ive a car"<< end1 void f(vehicle v)ydr ive; J void g vehicle*p pv->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 a generic vehicle" << endl;} }; class car :public vehicle{ public: void drive(){cout << "drive a car“ << endl;} }; void f(vehicle & v){ v.drive(); } void g(vehicle * pV){ pV->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 < "dive a generic vehicle < end1; 1 class car: plblic vehicle 指向基类对象,调 public: 用基类成员函数 vir tual hoid dr ive o scout < ve a car"<< end1 void f(vehicle v)/ydr ive; J void g(vehicle yy pv->drive O void mino( 指向派生类对象,调 结论: 基类指针指向不同派生类的对象,基类引用引用不同派 生类的对象时,执行的是相应派生类中的虚函数
21:53:08 例1:虚成员函数 class vehicle{ public: vir tual void drive() { cout << "drive a generic vehicle" << endl;} }; class car :public vehicle{ public: vir tual void drive(){cout <<"drive a car"<< endl;} }; void f(vehicle & v){ v.drive(); } void g(vehicle * pV){ pV->drive(); } void main(){ vehicle vh; car c; f(vh); f(c); //分别调用哪一个类中的drive()? g(&vh); g(&c); //分别调用哪一个类中的drive()? } 引用基类对象,调 用基类成员函数 引用派生类对象,调 用派生类成员函数 指向基类对象,调 用基类成员函数 指向派生类对象,调 用派生类成员函数 结论: 基类指针指向不同派生类的对象,基类引用引用不同派 生类的对象时,执行的是相应派生类中的虚函数