面试题答案
一键面试- Base类对象内存表现
- 内存布局:当创建一个
Base
类对象时,其内存中至少包含为类中数据成员分配的空间(在本题Base
类中无数据成员,暂不考虑数据成员内存)。同时,由于Base
类含有虚函数virtualFunc
,它会有一个虚函数表指针(vptr
)。 - 虚函数表指针(
vptr
):vptr
指向一个虚函数表(vtable
)。虚函数表是一个数组,数组中的每个元素是一个函数指针,指向对应的虚函数。在Base
类的虚函数表中,virtualFunc
的函数指针指向Base::virtualFunc
函数的实现。vptr
的存储位置通常在对象内存布局的开始位置(不同编译器可能有差异,但大多数现代编译器是这样)。
- 内存布局:当创建一个
- Derived类对象内存表现
- 内存布局:
Derived
类对象在内存中首先包含Base
类子对象部分,这部分和Base
类对象内存布局类似,有vptr
以及可能存在的Base
类数据成员(本题无)。接着是Derived
类新增的数据成员(如果有,本题无)。 - 虚函数表指针(
vptr
):Derived
类对象同样有一个vptr
,它也指向一个虚函数表。由于Derived
类继承自Base
类并覆盖了virtualFunc
,Derived
类的虚函数表和Base
类虚函数表结构相似,但对于被覆盖的virtualFunc
,其虚函数表中的函数指针指向Derived::virtualFunc
函数的实现。vptr
在Derived
类对象中的存储位置也通常在对象内存布局开始位置(包含Base
类子对象部分的开始位置)。
- 内存布局:
- 多态调用时对象内存结构的影响
- 多态原理:在多态调用中,如
Base* ptr = new Derived(); ptr->virtualFunc();
。首先,通过ptr
指针找到Derived
类对象内存起始位置,从而获取vptr
。vptr
指向Derived
类的虚函数表。 - 函数调用:从虚函数表中根据
virtualFunc
在表中的索引找到对应的函数指针,该指针指向Derived::virtualFunc
,于是调用的是Derived
类中覆盖后的virtualFunc
函数实现。这种机制使得通过基类指针或引用调用虚函数时,能够根据对象的实际类型(运行时类型)来调用正确的函数,实现多态行为。内存结构中vptr
和虚函数表的存在是实现多态的关键,它们在运行时动态确定要调用的函数,而非在编译时根据指针类型静态确定。
- 多态原理:在多态调用中,如