文章目录
一、虚函数表
虚函数表是一块连续的内存,每个内存单元中记录一个JMP指令的地址。
二、首先讲一下结论:
- 首先,虚函数表在编译时候就已经确定;
- 对象在构造前就已经分配好内存,在进入构造函数之前就已经将虚函数表地址给了对象了;
- 进一步的,虚函数表给对象,在初始化列表之前;
- 我们都知道初始化列表先于构造函数函数体实现;
于是顺序如下:
1.构造父类;
2. 将子类虚函数表地址给子类对象;
3. 初始化列表进行初始化;
4. 构造函数本体;
- 构造父类的时候,也是这样一个步骤;
- 最终的 虚函数表地址,被最外面的子类的 虚函数表地址 所覆盖;
三、证明
- C++代码:
class base
{
public:
virtual void func()
{
cout << "base::func()" << endl;
}
base()
{
func();
cout << "base()" << endl;
}
};
class person : public base {
public:
int *a;
virtual void func()
{
cout << "person::func()" << endl;
}
person():a(0)
{
func();
cout << "person()" << endl;
}
~person()
{
func();
cout << "~person()" << endl;
}
};
int main() {
person p1;
return 0;
}
- 构造
person
类,先去构造父类base
类:
- 构造
base
类,先将父类base
类 的 虚函数表地址 放在寄存器中;
- 构造完父类;
- 子类虚函数表地址给寄存器;最终还是给this 指针了,也就是对象地址第一个位置;
- 初始化列表;
- 最后再进入构造函数函数体;