多态分为两类
- 静态多态: 函数重载 运算符重载,复用函数名。
- 动态多态: 派生类和虚函数运行时多态。
区别
静态多态的函数地址早绑定: 编译阶段确定函数地址
动态多态的函数地址晚绑定: 运行阶段确定函数地址
静态多态经常见,这里就不讲了
动态多态满足关系
- 存在继承关系
- 子类重写父类虚函数(虚函数 关键字 virtual)
- 父类指针或引用 执行子类对象
动态多态原理剖析
#include<iostream>
#include<string>
using namespace std;
class animal {
public:
virtual void speak() {//虚函数
cout << "我是小妖精" << endl;
}
};
class dog :public animal {
public:
void speak() {
cout << "我是小狗,汪汪汪!" << endl;
}
};
void test(animal& ani) {//父类通过引用执行子类对象
ani.speak();
}
int main() {
/*animal* f1 =new dog; //指针方式
f1->speak();
animal& f2 = stu;//引用方式
f2.speak();*/
dog stu;
test(stu); //我是小狗,汪汪汪! 引用方式
}
首先 虚函数会产生一个 vfptr(虚拟函数表指针) 然后虚拟函数指针会指向一个vttable(虚拟函数表)
vftable中储存的是虚函数的地址 在子类继承父类时会继承父类的一切,包括vftable
而重写子类对象会产生新的vftable去覆盖子类中继承的vftable
所以上述例子中
void test(animal& ani) {
ani.speak();
}
speak为小狗叫声而不是动物叫声。