0. 提出问题
什么是多态?
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。
多态氛围哪几类?
多态可以分为静态多态和动态多态。
1. 静态多态
又称编译期多态,即在系统编译期间就可以确定程序将要执行哪个函数。例如:函数的重载,对象名加点操作符执行成员函数,类成员运算符指定的运算等,都是静态多态,其中,重载是在形成符号表的时候,对函数名做了区分,从而确定了程序执行到这里将要执行哪个函数,对象名加点操作符执行成员函数和类成员运算符指定的运算是通过this指针来调用的。
class A {
public:
A(){}
void fun(){}
void fun(int x){
val = x;
}
private:
int val;
};
int main(){
A a;
a.fun();
a.fun(10);
return 0;
}
这里定义了一个A类,有一个成员函数和一个成员,我们将程序的部分汇编代码截取出来如下图:
我们可以看到这里直接是一个lea指令将a对象的地址放入寄存器eax中,也就是对象的this指针,然后用call指令就可以跳转到Set函数,也就是说其汇编代码在此时就知道应该要去到哪个地方之行哪个函数,这就是静态多态,也叫编译时多态。
2. 动态多态
#include<iostream>
using namespace std;
class A {
public:
A(int a = 10) :_a(a) {}
virtual void Get() {
cout << "A:: _a=" << _a << endl;
}
public:
int _a;
};
class B : public A {
public:
B(int b = 20) :_b(b) {}
void Get() {
cout << "B:: _b=" << _b << endl;
}
public:
int _b;
};
int main() {
A a1;
B b1;
A* ptr1 = &a1;
ptr1->Get();
ptr1 = &b1;
ptr1->Get();
return 0;
}
/*
输出结果:
A:: -a=10
B:: _b=20
*/
这说明确实是实现了不同调用,而且是在运行时,那么虚函数的底层到底是怎么实现的呢,我们来看一下汇编代码及其对象模型:
通过上图的汇编代码,我们看到这里做了一系列的指针解引用处理,最后确定了eax中应该存放的this指针的值,要搞清楚这个必须要搞清楚子类的对象模型。