第八章 多态性和虚函数
8.1 多态性
静态联编所支持的多态性称为编译时的多态性。当调用重载函数时,编译器可以根据调用时使用的实参在编译时就确定下来应调用哪个函数。动态联编所支持的多态性称为运行时的多态性,这由虚函数来支持。虚函数类似于重载函数,但与重载函数的实现策略不同,即对虚函数的调用使用动态联编。
8.1.1 静态联编中的赋值兼容性及名字支配规律
对象的内存地址空间中只包含数据成员,并不存储有关成员函数的信息。这些成员函数的地址翻译过程与其对象的内存地址无关。
声明的基类指针只能指向基类,派生类指针只能指向派生。它们的原始类型决定它们只能调用各种的同名函数area。
8.1.2 动态联编的多态性
当编译系统编译含有虚函数的类时,将为它建立一个虚函数表,表中的每一个元素都指向一个虚函数的地址。此外,编译器也为类增加一个数据成员,这个数据成员是一个指向该虚函数表的指针,通常称为vptr。
虚函数的地址翻译取决于对象的内存地址。编译器为含有虚函数类的对象首先建立一个入口地址,这个地址用来存放指向虚函数表的指针vptr,然后按照类中虚函数的声明次序,一一填入函数指针。当调用虚函数时,先通过vptr找到虚函数表,然后再找出虚函数的真正地址。
派生类能继承基类的虚函数表,而且只要是和基类同名(参数也相同)的成员函数,无论是否使用virtual声明,它们都自动称为虚函数。如果派生类没有改写继承基类的虚函数,则函数指针调用基类的虚函数。如果派生类改写了基类的虚函数,编译器将重新为派生类的虚函数建立地址,函数指针会调用改写过的虚函数。
虚函数的调用规则是:根据当前对象,优先调用对象本身的成员函数。这和名字支配规律类似,不过虚函数是动态联编的,是在执行期“间接”调用实际上欲联编的函数。
8.2 虚函数
一旦基类定义了虚函数,该基类的派生类中的同名函数也自动称为虚函数。
8.2.1 虚函数的定义
虚函数只能是类中的一个成员函数,但不能是静态成员,关键字virtual用于类中该函数的声明中。
当在派生类中定义了一个同名的成员函数时,只要该成员函数的参数个数和相应类型以及它的返回类型与基类中同名的虚函数完全一样,则无论是否为该成员使用virtual,它都将成为一个虚函数。
8.2.2 虚函数实现动态性的条件
关键字virtual指示C++编译器对调用虚函数进行动态联编。这种多态性是程序运行到需要的语句处才动态确定的,所以称为运行时的多态性。不过,使用虚函数并不一定产生多态性,也不一定使用动态联编。例如,在调用中对虚函数使用成员名限定,可以强制C++对该函数的调用使用静态联编。
产生运行时的多态性有如下3个前提:
(1)类之间的继承关系满足赋值兼容性规则。
(2)改写了同名函数。
(3)根据赋值兼容性规则使用指针(或引用)。
由于动态联编是在运行时进行的,相对于静态联编,它的运行效率比较低,但它可以使程序员对程序进行高度抽象,设计出可扩充性好的程序。
8.2.3 构造函数和析构函数调用虚函数
在构造函数和析构函数中调用虚函数采用静态联编,即他们所调用的虚函数是自己的类或基类中定义的函数,但不是任何在派生类中重定义的虚函数。
目前推荐的C++标准不支持虚构造函数。由于析构函数不允许有参数,因此一个类只能有一个虚析构函数。虚析构函数使用virtual说明。只要基类的析构函数被说明为虚函数,则派生类的析构函数,无论是否使用virtual进行说明,都自动地成为虚函数。
delete运算符和析构函数一起工作(new和构造函数一起工作),当使用delete删除一个对象时,delete隐含着对析构函数的一次调用,如果析构函数为虚函数,则这个调用采用动态联编。一般来说,如果一个类中定义了虚函数,析构函数也应说明为虚函数,尤其是在析构函数要完成一些有意义的任务时,例如,释放内存。
如果基类的析构函数为虚函数,则在派生类为定义析构函数时,编译器所生成的析构函数也为虚函数。
8.2.4 纯虚函数与抽象类
在许多情况下,不能再基类中为虚函数给出一个有意义的定义,这时可以将它说明为纯虚函数,将其定义留给派生类去做。说明纯虚函数的一般形式如下:
class 类名{
virtual 函数类型 函数名(参数列表)=0;
};
一个类可以说明多个纯虚函数,包含有纯虚函数的类称为抽象类。一个抽象类只能作为基类来派生新类,不能说明抽象类的对象。但可以说明指向抽象类对象的指针(或引用)。
从一个抽象类派生的类必须提供纯虚函数的实现代码,或在该派生类中仍将它说明为纯虚函数,否则编译器将给出错误信息。这说明了纯虚函数的派生类仍是抽象类。如果派生类给了某类所有纯虚函数的实现,则该派生类不再是抽象类。
如果通过同一个基类派生一系列的类,则将这些类总称为类族。抽象类的这一特点保证了进度类族的每个类都具有(提供)纯虚函数所要求的行为,进而保证了围绕这个类族所建立起来的软件能正常运行,避免了这个类族的用户由于偶然失误而影响系统正常运行。
抽象类至少含有一个虚函数,而且至少有一个虚函数是纯虚函数,以便将它与空的虚函数区分开来。下面是两种不同的表示方法:
virtual void area()=0;
virtual void area(){}
在成员函数内可以调用纯虚函数。因为没有为纯虚函数定义代码,所以在构造函数或虚构函数内调用一个纯虚函数将导致程序运行错误。
8.3 多重继承与虚函数
8.4 类成员函数的指针与多态性
在派生类中,当一个指向基类成员函数的指针指向一个虚函数,并且通过指向对象的基类指针(或引用)访问这个虚函数时,仍发生多态性。
分享到:
相关推荐
### C++多态性与虚函数知识点解析 #### 一、多态性的概念 多态性是面向对象编程的一个...通过这些实验,你可以更深入地理解和掌握C++中的多态性、虚函数以及相关的高级特性。这些知识对于开发复杂的应用程序至关重要。
编译时多态性通过函数和运算符的重载来实现,而运行时多态性通过继承和虚函数来实现。 8.1 普通成员函数重载 C++语言中,普通成员函数重载是指在同一作用域中允许多个函数使用同一函数名的措施。函数重载是C++程序...
### 多态性与虚函数知识点详解 #### 一、多态性概念 **多态性**是面向对象编程中的一个重要特性,它允许子类对象替换父类对象,从而达到程序...理解并熟练掌握虚函数和多态性的使用对于编写高质量的C++程序至关重要。
综上所述,C++的多态性是通过函数重载、虚函数和继承等机制实现的。这些特性使得C++成为一种强大的面向对象编程语言,可以编写出更加灵活和可维护的代码。理解并熟练运用多态性,对于提升C++编程水平至关重要。
C++语言概述 第2章 数据类型和表达式 第3章 预处理和语句 第4章 函数和作用域 第5章 类和对象(一) 第6章 类和对象(二) 第7章 继承性和派生类 第8章 多态性和虚函数 第9章 ...
多态性主要通过三种方式实现:函数重载、运算符重载和虚函数。 函数重载允许我们在同一个作用域内使用相同的函数名但具有不同的参数列表,编译器会根据传入的参数类型和数量来选择合适的函数进行调用。例如,在处理...
8. 虚函数与多态性,多态性通过虚函数实现,虚函数允许派生类覆盖基类中的方法,使得基于基类类型的指针或引用能够调用派生类的方法。 在具体的学习中,应该注意以下几点: - 类的继承是实现代码复用的手段,但更...
### 虚函数内存模型详解 #### 一、引言 在C++中,虚函数是一种重要的特性,它使得派生类能够重写基类的行为。为了支持这种动态绑定机制,...理解虚函数内存模型有助于更好地掌握C++中的多态性原理及其内部实现机制。
"第八章 多态性和虚函数"进一步阐述了多态性这一关键概念。多态性允许不同的对象对同一消息做出不同的响应,这通常通过虚函数实现。虚函数使得基类指针或引用可以调用派生类的方法,增强了代码的灵活性和扩展性。 ...
9. **静态多态(Static Polymorphism)**:非虚函数和模板函数提供了编译时的多态性,与虚函数的运行时多态性不同。 10. **运算符重载与虚函数**:C++允许运算符作为成员函数重载,也可以声明为虚函数以实现多态。 ...
### C++高级程序设计实验...以上内容覆盖了实验的主要知识点,包括运算符重载、类型转换、虚函数和多态性的实现方式,以及具体的代码示例。这有助于加深对C++多态性和类型转换的理解,并能实际应用于具体问题的解决。
第1章 C++的初步知识 第2章 数据类型与表达式 第2篇 面向过程的程序设计 第3章 程序设计初步 第4章 函数与预处理 第5章 数组 第6章 指针 ...第12章 多态性与虚函数 第13章 输入输出流 第14章 C++工具
第1章 C++的初步知识 第2章 数据类型与表达式 第2篇 面向过程的程序设计 第3章 程序设计初步 第4章 函数与预处理 第5章 数组 第6章 指针 ... 第12章 多态性与虚函数 第13章 输入输出流 第14章 C++工具
### C++中的虚函数及其...虚函数的引入极大地增强了语言的灵活性,使得程序能够更好地支持多态性和代码重用。通过虚函数表和虚表指针的设计,C++能够高效地实现运行时多态,这也是C++区别于其他语言的一个重要特点。
C++程序设计 第1章 绪论 第9章 运算符重载 第2章 数据类型和表达式 第10章 静态成员与友元 第3章 控制语句 第11章 继承和派生类 第4章 函数 第12章 模板 第5章 数组 第13章 多态性与虚函数 第...
第1篇 基 本 知 识 第1章 C++的初步知识 第2章 数据类型与表达式 第2篇 面向过程的程序设计 第3章 程序设计初步 第4章 函数与预处理 第5章 数组 ...第12章 多态性与虚函数 第13章 输入输出流 第14章 C++工具
总 目 录 第 1 篇 基 本 知 识 第 1 章 C++的初步知识 第 2 章 数据类型与表达式 第 2 篇 面向过程的程序设计 第 3 章 程序设计初步 ...第 12 章 多态性与虚函数 第 13 章 输入输出流 第 14 章 C++工具
在C++中,虚函数的主要作用是实现多态性,即允许父类型的指针或引用调用子类重写的成员函数。这种机制使得程序员能够编写更灵活、可扩展的代码。例如: ```cpp class Base { public: virtual void func() { cout ;...
全国计算机二级c++复习课件 第1篇 基 本 知 识 第1章 C++的初步知识 第2章 数据类型与表达式 第2篇 面向过程的程序设计 第3章 程序设计初步 ... 第12章 多态性与虚函数 第13章 输入输出流 第14章 C++工具
大学C++课本,谭浩强版,电子教案。 第1篇 基 本 知 识 第1章 C++的初步知识 第2章 数据类型与表达式 第2篇 面向过程的程序设计 ... 第12章 多态性与虚函数 第13章 输入输出流 第14章 C++工具