C++中针对虚基类的static_cast是否会触发运行时vptr查询?
问题
假设有如下代码:
struct Granny { int g; }; struct Mom : virtual Granny { int m; }; struct Son : Mom { int s; }; int main() { int x; std::cin >> x; Mom* mom = (x ? new Son : new Mom); Granny* granny = static_cast<Granny*>(mom); }
这些类并非多态类(Granny没有虚函数),但根据x的取值,mom指针指向的对象内存布局会有所不同:Granny子对象相对于对象起始地址的偏移量为16字节或12字节。
问题:此处的static_cast是否不会执行“简单指针移位”,而是编译为“解引用mom对象的vptr(虚表指针),通过索引查找虚偏移量,最终按该偏移量调整指针”的逻辑?即static_cast会增加两个额外的运行时操作吗?如果不是,请解释实际发生的行为。
解答
是的,这里的static_cast不会是编译期固定的指针移位,而是会触发运行时的虚表查询操作,具体逻辑和你描述的一致:
- 解引用
mom指针指向对象的vptr,获取对应的虚表地址; - 从虚表的特定位置读取
Granny子对象相对于当前对象起始地址的偏移量; - 用该偏移量调整
mom指针,得到最终的Granny*指针。
之所以需要运行时操作,核心原因是虚拟继承的特性:当类使用虚拟继承时,虚拟基类子对象的偏移量不是固定的——它取决于实际创建的对象类型(这里可能是Mom或Son)。编译期无法预知x的取值,也就无法确定mom实际指向的对象类型,自然没法硬编码一个固定的偏移量。
另外要注意:哪怕Granny本身没有虚函数,只要类(Mom)使用了虚拟继承,编译器就会在Mom和Son的对象中插入vptr,这个vptr的作用之一就是存储虚拟基类的偏移信息,用于这种跨类型的指针转换。
内容的提问来源于stack exchange,提问作者gh_shark
相关产品推荐
相关产品推荐

