多态的现象,同样的调用语句有着不同的表现形态。
#include <iostream>
using namespace std;
class animal
{
public:
virtual void func() = 0;//纯虚函数
protected:
private:
//char *voice = "我是annimal怎么叫?";
};
class duck:public animal
{
public:
virtual void func()//纯虚函数重写
{
cout << voice << endl;
}
protected:
private:
char *voice = "我是鸭子,嘎嘎嘎";
};
class cat:public animal
{
public:
virtual void func()//纯虚函数重写
{
cout << voice << endl;
}
protected:
private:
char *voice = "我是小猫,喵喵喵";
};
//框架
void cry(animal *p)//赋值兼容性原则,可传递子类指针
{
p->func();
}
int main()
{
duck d1;
cat c1;
cry(&d1);//运行效果:我是鸭子,嘎嘎嘎
cry(&c1);//运行效果:我是小猫,喵喵喵
system("pause");
return 0;
}
上例中同样是调用cry()函数,不同的对象传入,可以调用各自对象中的方法,产生不同的现象。这个现象便是多态。
从上述代码中可以总结出多态产生的条件有三个:
1、父类子类继承关系。
2、(纯)虚函数重写。
3、父类指针(引用)指向子类对象。
virtual关键字,告诉编译器这个函数要支持多态;不要根据指针类型判断如何调用;而是要根据指针所指向的实际对象类型来判断如何调用。
C++多态实现原理:
当类中声明(纯)虚函数时,编译器会在类中生成一个虚函数表
虚函数表是一个存储类成员函数指针的数据结构
虚函数表是由编译器自动生成与维护的
virtual成员函数会被编译器放入虚函数表中
存在虚函数时,每个对象中都有一个指向虚函数表的指针(vptr指针)
拿上述代码duck类来说,编译的时候,编译器会自动为duck加上一个VPTR指针,duck当执行d1类初始化的时候,编译器就会自动创建一个d1的虚函数表,存放d1的func函数指针,而VPTR也会指向这个虚函数表。