多态对象的内存结构
这篇文章我们通过具体的案例来谈一谈多态的具体内存结构:
class Base
{
public:
virtual void Func1()
{
cout << "Func1()" << endl;
}
virtual void Func2()
{
cout << "Func2()" << endl;
}
void Func3()
{
cout << "Func3()" << endl;
}
private:
int _b = 1;
};
class Derive : public Base
{
public:
virtual void Func1()
{
cout << "Dereve:Func1()" << endl;
}
virtual void Func4()
{
cout << "Func4()" << endl;
}
};
int main()
{
Base a;
Derive b;
return 0;
}
我们将通过内存布局来直观展示 Base
类对象 a
和 Derive
类对象 b
在内存中的结构。由于 Base
类和 Derive
类都有虚函数,它们会各自包含一个虚指针(vptr
)指向对应类的虚表。
1. Base 类的对象 a
的内存布局
Base a;
内存结构:
+--------------------+
| vptr (虚指针) | -> 指向 Base 类的虚表
+--------------------+
| _b (private int) | -> 值为 1
+--------------------+
vptr
指向 Base
类的虚表。Base
类的虚表如下:
Base 类的虚表:
+----------------------------+
| &Base::Func1 | -> 指向 Base 类的 Func1 实现
+----------------------------+
| &Base::Func2 | -> 指向 Base 类的 Func2 实现
+----------------------------+
Func1
和Func2
是虚函数,所以它们的函数指针存储在虚表中。Func3
是普通成员函数,不在虚表中,它直接通过类调用,不需要虚表查找。_b
是Base
类的私有成员变量,值为 1,占用内存。
2. Derive 类的对象 b
的内存布局
Derive b;
内存结构:
+--------------------+
| vptr (虚指针) | -> 指向 Derive 类的虚表
+--------------------+
| _b (继承自 Base) | -> 值为 1
+--------------------+
vptr
指向 Derive
类的虚表。Derive
类的虚表如下:
Derive 类的虚表:
+----------------------------+
| &Derive::Func1 | -> 指向 Derive 类的 Func1 实现
+----------------------------+
| &Base::Func2 | -> 指向 Base 类的 Func2 实现
+----------------------------+
| &Derive::Func4 | -> 指向 Derive 类的 Func4 实现
+----------------------------+
Derive
类重写了Func1
,所以虚表中的Func1
指针指向Derive
类的Func1
实现(Derive::Func1
)。Func2
没有被重写,因此虚表中的Func2
仍然指向Base::Func2
。Derive
类新增了一个虚函数Func4
,所以Func4
的地址也被存储在虚表中。_b
是从Base
类继承的成员变量,值为 1。
3.总结
Base a
的内存布局:- 包含一个虚指针(
vptr
),指向Base
类的虚表。 - 包含一个私有成员变量
_b
,值为 1。
- 包含一个虚指针(
Derive b
的内存布局:- 包含一个虚指针(
vptr
),指向Derive
类的虚表。 - 继承了
Base
类的私有成员变量_b
,值为 1。
- 包含一个虚指针(