系列汇总讲解,请移步:
C++语法|虚函数与多态详细讲解系列(包含多重继承内容)
在本节中,我们主要讨论一个问题:
虚函数的调用一定是动态绑定吗?答案肯定是否定的!
在类的构造函数中,调用虚函数,也是静态绑定(构造函数中调用其他函数(虚),不会发生动态绑定)
接下来我们通过实验代码来明确该问题:
静态绑定虚函数
有以下类:
class Base {
public:
Base(int data = 10) : ma(data) { cout << "Base()" << endl; }
virtual void show() { cout << "Base::show()" << endl; }
protected:
int ma;
};
class Derive : public Base {
public:
Derive(int data = 20) : Base(data), mb(data) { cout << "Derive()" << endl;}
void show() {cout << "Derive::show()" << endl; }
private:
int mb;
};
测试函数如下:
int main () {
Base b;
Derive d;
b.show(); //虚函数
d.show(); //虚函数
return 0;
}
你觉得调用结果如何呢?
你答对了吗?这两个虚函数的调用都是静态绑定,那也就是说用对象本身调用虚函数,其实是静态绑定。
他们的汇编底层均为:
call Base::show()
call Derive::show()
动态绑定调用虚函数
现在我们用基类指针指向基类对象,然后调用show()方法。
Base *pb1 = &b;
pb1->show();
pb1->show();
这里的汇编如下:
mov rdx, QWORD PTR [rax]
mov rax, QWORD PTR [rbp-8]
mov rdi, rax
竟然是动态绑定!也就是说由指针调用虚函数,才会发生动态绑定(这里调用的也是自己的方法)!这是为什么?
为什么指针调用虚函数就发生动态绑定了?
<个人回答,说的不对非常高兴读者能指出来>
其实这是C++语法决定的,其实指针或引用的是实现动态绑定的基础,所以在C++语法中,指针或者引用的实际对象类型决定了应该调用哪个方法版本。如果我们不能保证
Base *pb1 = &b;
pb1->show();
这个调用时动态绑定,
那你又如何保证
Base *pb2 = &d;
pb2->show();
这个绑定是动态绑定呢?
所以对指针的相关函数调用处理必须得是运行时的,而不能是编译时的处理