C++ 多态和重载、重写(覆盖)的关系
前言
本文旨在通俗易懂的描述各个概念,自己吃了不少C++的苦,这两天从零看了一遍,写一下读书笔记记录自己对各个概念的见解。
C++中,多态分为静态多态和动态多态,在此之前需要先了解静态联编和动态联编的概念。
1. 静态联编和动态联编
将源代码中的函数调用解释为执行特定的函数代码块被称为函数名联编。
C++存在函数重载,编译器必须根据函数参数以及函数名才能确定使用哪个函数。C/C++编译器可以在编译过程完成这种联编。在编译过程中进行的联编被称为静态联编。由于虚函数的存在,使用哪一个函数是不能在编译时确定的,因为编译器不知道用户将选择哪种类型的对象。所以,编译器必须生成能够在程序运行时选择正确的虚方法的代码,这被称为动态联编。(摘抄自C++ Primer Plus 13.4节 静态联编和动态联编,还是具有一定权威性的……)
静态联编好理解,即函数调用是确定好的,不会改变。动态联编只需要记住因为虚函数的存在即可,虚函数在运行时要根据对象类型(指向基类还是父类)确定调用函数,具有不确定性。
为什么动态联编这么好,不将其设置为默认编译类型?
为了使程序能够在运行阶段
2. 多态
先贴一下菜鸟教程中关于多态的描述:菜鸟教程-多态。
术语“多态”指的是有多种形式,因此函数多态允许函数可以由多种形式。C++ 多态意味着调用成员函数时,会根据调用函数的特征标或者对象的类型来执行不同的函数。特征标–>静态多态,对象的类型–>动态多态。
2.1 静态多态
即函数重载和泛型编程(函数模板)。
函数重载可以让用户使用多个同名函数,因此对名称进行了重载。函数重载的关键是函数的参数列表(包括参数数目,顺序,类型)——也成为函数特征标。C++允许定义名称相同的函数,条件是它们的特征标不同。编译器会根据特征标的不同,找到最合适的函数。
注意:1. 类型引用和类型本身视为同一个特征标;2. 函数类型 | 返回值类型实现不了重载,必须是特征标;
举例:
long gronk(int n, float m);
long gronk(float n, int m);//重载,特征标不同
int gronk(int n, float m);//不重载,特征标不同,返回值不同没用
int gronk(int & n, float & m);//不重载,特征标不同,类型引用和类型本身视为同一个特征标
泛型编程即函数模板,是通用的函数描述,它们使用泛型来定义函数,其中泛型可用具体的类型(如int