多态是C++面向对象三大特性之一
多态分为静态多态和动态多态
静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名。
动态多态:类的继承和虚函数实现运行时的多态。
二者的区别:
静态多态:静态多态的函数地址早绑定 - 编译阶段确定函数地址
动态多态:动态多态的函数地址晚绑定 - 运行阶段确定函数地址,也就是在运行的时候才决定去调用哪个函数
(由于早晚绑定,就会产生一些区别)
1.下面复习一下,有无虚函数的差别。(其实就是子类对象的是否覆盖的问题) 虚函数声明只能写在类定义的函数原型声明中,而不能写在成员函数实现之时。
//多态满足条件:
//1、有继承关系
//2、子类重写父类中的虚函数
//多态使用:
//父类指针或引用指向子类对象
#include<iostream>
using namespace std;
class Animal {
public:
void speak() { //这里要设置虚函数,下面父类引用调用就会调用子类的成员,要是不设置,父类引用就只能访问子类从父类中继承的成员。
cout << "animal is speaking" << endl;
}
};
class cat :public Animal {
public:
void speak() {
cout << "cat is speaking" << endl;
}
};
//父类引用或者父类指针的时候才会体现出虚函数有无的差异,通过子类直接无法体现
void speak(Animal &ani) { //实际就相当于Animal& ani=c;
ani.speak();
}
void test() {
cat c;
speak(c);
}
int main() {
test();
}
虚函数动态绑定的实现原理:
先讲述两个概念:虚函数表(vftable)和虚函数表指针(vfptr)
设置了虚函数后:二者随即出现.
下面两幅图是通过开发人员工具得到的虚函数表示意图:可以验证上面的说法。
顺带介绍如何使用vs开发人员工具来查看虚函数列表和内存分布的方法:
1.先打开 Developer Command Prompt
2.然后回到我们建立的cpp工程查看路径(不要直接复制完整路径)
3.回到Developer Command Prompt的命令行窗口
输入: cd 刚才复制的路径
定位到该文件夹之后 再输入dir
4.下面再使用c1 /d1 reportSingleClassLayout命令(小心,cl这里的是一个英文字母l,而不是数字1,后面那个d1才是数字1)
以这个为例: cl /d1 reportSingleClassLayoutAnimal "赋值运算符=重载.cpp"
前面的白色部分就是固定代码部分,红字表示你想看的类名,绿字表示cpp名字,我们只需要输入前几个字符(连双引号都不用打),然后按tab键就能自动补全。
然后就能出来我们想要的虚函数表:(如果代码改动,一定要编译后再来重新查看,否则和原结果一样)