
第6章多态性与虚函数 6.1多态性的概念 6.3虚函数 6.2一个典型的例子 6.4纯虚函数与抽象类
1 6.1 多态性的概念 6.3 虚函数 6.2 一个典型的例子 6.4 纯虚函数与抽象类 第6章 多态性与虚函数

6.1多态性的概念 多态性(polymorphism)是面向对象程序设计的 重要特征。利用多态性,可以设计一个易于扩展的系 统。 什么叫多态? 一种事物的多种形态。 >在C++中,是指具有不同功能的函数可以用同一个函 数名。 >面向对象方法中描述多态性:向不同的对象发送同一 个消息,不同的对象在接收时会产生不同的行为(即方 法)
2 6.1 多态性的概念 多态性( polymorphism ) 是面向对象程序设计的 重要特征。利用多态性,可以设计一个易于扩展的系 统。 什么叫多态? 一种事物的多种形态。 ➢在C++中,是指具有不同功能的函数可以用同一个函 数名。 ➢面向对象方法中描述多态性:向不同的对象发送同一 个消息,不同的对象在接收时会产生不同的行为(即方 法)

6.1多态性的概念 多态性分为以下两类: ,静态多态性:编译时。编译器对源程序进行编 译时就可以确定所调用的是哪一个函数。 实现方式:函数重载(普通函数、成员函数、构 造函数)运算符重载 动态多态性:运行时。在程序运行过程中根据 具体情况来确定调用的是哪一个函数。 实现方式:虚函数
3 多态性分为以下两类: ➢ 静态多态性:编译时。编译器对源程序进行编 译时就可以确定所调用的是哪一个函数。 实现方式:函数重载(普通函数、成员函数、构 造函数) 运算符重载 ➢ 动态多态性:运行时。在程序运行过程中根据 具体情况来确定调用的是哪一个函数。 实现方式: 虚函数 6.1 多态性的概念

例6.1:基类指针指向派生类对象 ① #include void display()∥与基类同名函数 ② {cout ③ display();∥调用基类成员函数 int num;string name;float score; pt=&g1;∥指向派生类对象g1, ④ }; pt->display(); class graduate public student ⑤ (public:graduate (int n,string nam, float s,float p): /仅输出了派生类对像的基类数据成 student (n,nam,s),pay(p){} 员,因为它调用的是基类成员函 数display!
4 例6.1: 基类指针指向派生类对象 ① #include ② #include ③ using namespace std; ④ class student //定义基类 ⑤ {public: ⑥ student(int n,string nam, float s) ⑦ { num= n; name= nam; score= s; } ⑧ void display( ) ⑨ {coutdisplay( ); // 调用基类成员函数 ⑬ pt = &g1; // 指向派生类对象g1, ⑭ pt->display( ); ⑮ } //仅输出了派生类对象的基类数据成 员,因为它调用的是基类成员函 数display!

一龙生九子,九子各不同。 继承性 多态性 2025/4/6
一龙生九子,九子各不同。 继承性 多态性 2025/4/6 5

继承性为实现多态性提供了两个基本条件: (1)在具有派生层次结构的各个类中,可以定 义同原型而操作各异的成员函数,为不同类的 对象响应同一消息实现多样性提供了条件。 (2)使用基类指针既可以访问基类对象又可 以访问派生类对象,为动态确定接收同一消息 的不同类对象提供了条件。 擎只有这两个条件能否实现多态性呢? 2025/4/6
继承性为实现多态性提供了两个基本条件: 只有这两个条件能否实现多态性呢? (1)在具有派生层次结构的各个类中,可以定 义同原型而操作各异的成员函数,为不同类的 对象响应同一消息实现多样性提供了条件。 (2)使用基类指针既可以访问基类对象又可 以访问派生类对象,为动态确定接收同一消息 的不同类对象提供了条件。 2025/4/6 6

例题6-1、派生类对象替换基类对象 #include class Pet 1/基类 public: void speak({cout<<"How does a pet speak ?"<<endl;} }; class Cat public Pet /派生类Cat public: void speak(cout<<"miao!miao!"<<endl; }; class Dog public Pet /派生类D0g public: void speak() cout<<"wang!wang!"<<endl; a25146
#include class Pet //基类 {public: void speak() { cout<<"How does a pet speak ?"<<endl; } }; class Cat : public Pet //派生类Cat {public: void speak() { cout<<"miao!miao!"<<endl; } }; class Dog : public Pet //派生类Dog {public: void speak() { cout<<"wang!wang!"<<endl; } }; 例题6-1、派生类对象替换基类对象 2025/4/6 7

void main() Pet pl,*ptr=&pl; IA Dog dogl; 输出如下: Cat cat1; ptr->speak();//B How does a pet speak? ptr=&cat1; ptr->speak(); IIC How does a pet speak? ptr=&dogl; ptr->speak();//D How does a pet speak? 解决方法:采取“动态连接”的方式进行 编译,即引入虚函数。 25/4
void main() { Pet p1,*ptr=&p1; //A Dog dog1; Cat cat1; 输出如下: ptr->speak(); //B ptr = &cat1; ptr->speak(); //C ptr = &dog1; ptr->speak(); //D } How does a pet speak? How does a pet speak? How does a pet speak? 原因:在编译过程中,当编译到A行时,将实例*ptr中 的函数speak ()确定为类Pet中的成员函数,且采用的是 “静态联编”方式,在运行过程中,不管ptr指向哪个派 生类对象,函数ptr->speak()都不会改变为派生类的版本。 解决方法:采取“动态连接”的方式进行 编译,即引入虚函数。 2025/4/6 8

6.3虚函数 内容提要 、 虚函数 二、虚函数的实现原理(虚函数表) 三、小结 2025/4/6
6.3 虚函数 内 容 提 要 一、虚函数 二、虚函数的实现原理(虚函数表) 三、小 结 2025/4/6 9

虚函数 虚函数是一种非静态的成员函数,说明虚函数的方法 如下: virtual《类型〉 〈函数名〉(〈参数表〉) 虚函数具有如下特征: ①虚函数是在基类和派生类中说明相同而实现不同 的成员函数。 ②基类中说明的虚函数具有下传给派生类的性质。 ③构造函数不能说明为虚函数,而析构函数可以说 明为虚函数。 2025/4/6
2025/4/6 10 虚函数是一种非静态的成员函数,说明虚函数的方法 如下: virtual 〈类型〉〈函数名〉(〈参数表〉) 虚函数具有如下特征: ① 虚函数是在基类和派生类中说明相同而实现不同 的成员函数。 ② 基类中说明的虚函数具有下传给派生类的性质。 ③ 构造函数不能说明为虚函数,而析构函数可以说 明为虚函数。 一、 虚函数