含纯虚基类的派生类共用体运行时行为解析
底层运行机制解析
首先明确几个核心底层逻辑:
- Union的内存特性:Union的所有成员共享同一块连续内存空间,
theDers.D1和theDers.D2的起始地址完全相同,整个union对象的内存大小等于其最大成员的大小(这里两个派生类大小一致,因为都仅继承了带纯虚函数的Base,无额外成员)。 - C++虚函数的实现原理:带有虚函数的类,其对象实例的内存布局最开头会包含一个虚表指针(vptr),该指针指向对应类的虚函数表(vtable)——虚表中存储了类的虚函数地址。当类的构造函数执行时,会将对象的vptr设置为当前类的虚表地址,这是保证虚函数多态调用的核心。
回到你的代码运行流程:
- 全局union对象
theDers通过构造函数初始化了D1,也就是执行了Der1的构造函数。此时,theDers对应的内存块中,vptr被设置为Der1类的虚表地址。 - 第一次调用
b->Func()时,通过b指向的对象中的vptr找到Der1的虚表,调用Der1::Func(),输出"Der1"。 - 当执行
b = &theDers.D2时,只是改变了指针b的指向,但**Der2的构造函数从未被调用过**——union不会自动构造未被初始化的成员,这块共享内存的vptr仍然是之前Der1构造时设置的那个,指向Der1的虚表。 - 第二次调用
b->Func()时,依然是通过内存中未被更新的vptr找到Der1的虚表,因此还是调用Der1::Func(),再次输出"Der1"。
本质上:你只是修改了指针的指向,但目标内存里的虚表指针根本没被更新成Der2的,因为Der2对象从未被正确构造过,虚函数调用的逻辑自然还是走Der1的实现。
内容的提问来源于stack exchange,提问作者Ashley Duncan
相关产品推荐
相关产品推荐

