C++中的多态性是面向对象初封装性,继承性之外的又一大特性。多态性也是一种泛型,利用多态性我们可以用不变的代码产生不同的处理结果。也可以说其是”一个接口,多种方法”。
1.虚函数的声明
虚函数的声明只虚在类内的函数声明前加上virtual即可
实例如下
class A
{
//fun1为普通函数
void fun1(void);
fun2为虚函数
virtual fun2(void);
}
需要强调的是,如果A被继承,则继承类中的fun2函数默认也是虚函数
2.多态的实现
想要实现一种接口,多种方法(即多态)所要必备的条件有俩个
(1)类之间要有继承关系
(2)基类中要有虚函数
具体实例如下
#include<iostream>
using namespace std;
class Base
{
public:
void fun1(void)
{
cout<<"I am Base fun1"<<endl;
}
virtual void fun2(void)
{
cout<<"I am Base fun2"<<endl;
}
};
class Derived:public Base
{
void fun1(void)
{
cout<<"I am Derived fun1"<<endl;
}
virtual void fun2(void)
{
cout<<"I am Derived fun2"<<endl;
}
};
int main(void)
{
Base test1;
Derived test2;
Base *p;
//将Derived类型对象的地址给Base类型的指针
p = &test2;
//调用fun1和fun2
p->fun1();
p->fun2();
return 0;
}
需要注意的是虚函数通过基类的指针或引用调用时,才会产生动态绑定
动态绑定的实现原理是由保存在基类开头的一张虚函数表实现的,想了解详情的可以戳这里http://blog.csdn.net/hackbuteer1/article/details/7475622
3.关于多态的要点
(1)override说明符
如果派生类定义了一个函数,与基类中的虚函数函数名形同而形参不同,这是合法的,只是对继承自基类的该函数实现了重载。但如果我们本意是要实现多态而不是重载,那么这就是个致命的错误,因为编译器不会为我们指出此错误。那么如何来避免此问题呢?C++11为我们提供了一个新的说明符overrid来解决此问题,它的使用方法如下
class A
{
public:
virtual void fun1();
virtual void fun2();
};
class B:public A
{
//在继承来的虚函数参数列表后加override说明符之后如果函数形式和基类的完全相同则正确,如此函数
void fun1(void)override;
//如果函数和基类继承来的形式不同,则编译器会报错
void fun2(void) override;
};
(2)回避虚函数
如果我们希望对虚函数的调用不要执行动态绑定而是执行某个固定版本,则使用作用域运算符可以实现这一点
//此例使用的是上面给出的实例中的类
Base test1;
Derived test2;
Base p = &test2;
//则此执行的是基类的fun2函数,而不是继承类
p->Base::fun2();
(3)纯虚函数
有时候我们基类中的某个虚函数并不需要在程序中执行,而只是为类给其子类们提供一个动态绑定的基础,那么我们就可以把该函数定义成纯虚函数
实例如下
class A
{
//纯虚函数
virtual void fun(void) = 0;
};