提问人:dRIFT sPEED 提问时间:8/31/2023 更新时间:8/31/2023 访问量:56
虚拟关键字如何导致动态绑定?
How virtual keyword leads to dynamic binding?
问:
我知道以下几点
编译器为每个包含至少一个虚拟函数的类构造一个虚拟表。它还向基类添加了一个指针(v_ptr)(假设它具有虚拟函数),并且该指针被每个派生类继承。创建类的对象时,会发出相同的指针来指向该对象所属类的虚拟表。
现在,如果我没记错的话,以上所有内容都只发生在编译时。如果是这样,那么请考虑以下示例 virtual 关键字如何导致动态绑定。
#include <iostream>
using namespace std;
class base {
public:
virtual void show()
{
cout << "base\n";
}
};
class derived:public base{
public:
void show()
{
cout << "derived\n";
}
};
int main()
{
base* ptr;
derived drv1;
ptr = &drv1;
ptr->show();
return(0);
}
在上面的代码中,动态绑定是如何在语句中发生的,因为我认为在编译时一切都是已知的来绑定函数。 通过它调用,指向其基础将包含指向其类的虚拟表v_ptr因此编译器仅在编译时知道要调用哪个表。ptr->show();
show()
ptr
derv1
show()
注 - 基表示从基类继承的部分。derv1
答:
2赞
j6t
8/31/2023
#1
在这一行中
derived drv1;
创建类的实例。为此,执行类的构造函数。(在此示例中,所有构造函数都是隐式声明和定义的,但这一事实没有区别。
- begins 的构造函数。它立即调用 的构造函数。
derived
base
- 的构造函数填充实例的虚拟表指针以指向 的虚拟调度表。
base
base
- 的构造函数结束后的 resumes 的构造函数。
derived
base
- 此时,它会将实例的虚拟表指针更改为指向 的虚拟调度表。
derived
关键是实例的演变发生在运行时,而不是在编译时。
当然,优化可能会将事情降低到在生成的程序集中看不到此过程的任何内容的水平(“去虚拟化”)。
评论