多态的基本概念:
多态是
C++
面向对象三大特性之一
多态分为两类:
静态多态
:
函数重载 和 运算符重载属于静态多态,复用函数名
动态多态
:
派生类和虚函数实现运行时多态
静态多态和动态多态区别:
静态多态的函数地址早绑定
-
编译阶段确定函数地址
动态多态的函数地址晚绑定
-
运行阶段确定函数地址
下面通过案例进行讲解多态:
//多态
//动物类
class Animal
{
public:
//函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
//猫类
class Cat :public Animal
{
public:
//重写,函数返回值类型 函数名 参数列表 完全相同
void speak()
{
cout << "小猫在说话" << endl;
}
};
//狗类
class Dog :public Animal
{
public:
void speak()
{
cout << "小狗在说话" << endl;
}
};
//执行说话的函数
//地址早绑定 编译阶段就能确定函数地址
//如果想执行让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定
//动态多态满足条件
// 1、有继承关系
//2、子类重写父类的虚函数
//动态多态使用
//父类的指针或者引用 指向子类对象
void doSpeak(Animal& animal) //Animal& animal=cat;
{
animal.speak();
}
void test01()
{
Cat cat;
doSpeak(cat);
Dog dog;
doSpeak(dog);
}
int main()
{
test01();
system("pause");
return 0;
}
总结:
多态满足条件:
1 有继承关系
2 子类重写父类中的虚函数
多态使用条件:
父类指针或引用指向子类对象
重写:函数返回值类型
函数名 参数列表 完全一致称为重写
多态的原理刨析:
不加virtual关键字:
加virtual关键字:
为什么加上 virtual关键字之后会变成四个字节? (指针)vfptr
写了一个虚函数,类的内部结构发生改变,多了一个指针(虚函数表指针),指向虚函数表,虚函数表的内部写的是虚函数的函数入口地址,当子类重写了虚函数,会把自身的虚函数表中的函数替换掉,替换成子类的虚函数,当用父类的引用去指向子类对象的时候,会从子类对象找函数接口入口地址。
两个类的内部结构如图如下:
验证:
不加virtual关键字:
加virtual关键字:
当子类没有发生重写的时候:
当子类发生重写的时候: