多态性
多态性的定义:只允许不同类的对象对同一消息作出相应反应,即同一消息可以根据发送对象的不同而采用的行为方式。这里的发送消息就是函数调用。
多态性分为:编译期多态(静态多态)和运行时多态(动态动态)。
编译时多态
编译期多态,正如其名,就是在编译期确定的一种多态性。这个在C++中主要体现在函数模板,这里需要注意的是函数重载和多态无关。
// 例1:函数模板体现出编译期多态
#include <iostream>
template <typename T>
T add(T a, T b)
{
T c = a + b;
return c;
}
int main()
{
int i1 = 1;
int i2 = 2;
int iResult = 0;
iResult = add(i1, i2);
std::cout << "The result of integer is " << iResult << std::endl;
double d1 = 1.1;
double d2 = 2.2;
double dResult = 0;
dResult = add(d1, d2);
std::cout << "The result of double is " << dResult << std::endl;
return 0;
}
即在编译期,编译器根据一定的最佳匹配算法确定函数模板的参数类型到底是什么,这就体现了编译期的多种状态。
运行时多态
运行期多态主要是指在程序运行的时候,动态绑定所调用的函数,动态地找到了调用函数的入口地址,从而确定到底调用哪个函数。在C++中,运行期多态主要通过虚函数来实现,并且一定要有继承关系。
定义父类指针并指向子类对象,此时用父类指针去调用一个特殊的函数,即父类中该函数是虚函数,而子类重写了这个虚函数,此时调用的这个函数就在运行期间动态地绑定到了指针实际所指的对象,即子类对象,从而去调用子类中的这个函数。
注意:
在继承中有三类函数:纯虚函数、虚函数、非虚函数。
非虚函数:当一个成员函数为非虚函数时,它在派生类中的行为就不应该不同。实际上,非虚成员函数表明了一种特殊性上的不变性,因为它表示的是不会改变的行为。所以,声明非虚函数的目的在于,使派生类强制继承函数的接口和实现。
纯虚函数:声明纯虚函数的目的是让派生类来继承函数接口而不是实现,而实现交由派生类来完成,派生类也必须重写该接口(如果要实例的话)。
虚函数:让派生类来继承函数接口和实现,而派生类可以重写该接口,但也可以调用基类的默认实现。