【问题标题】:How can static_cast be used with virtual inheritance?static_cast 如何与虚拟继承一起使用?
【发布时间】:2013-07-28 23:35:29
【问题描述】:

所以不可能通过虚拟继承使用static_cast进行向下转换,但是如何进行以下向上转换:

class Base {...};
class Derived : public virtual Base {...};

...

Derived *d = new Derived();
Base *b = static_cast<Base*>(d);

对象的内存布局:

[ derived part | base part ]

我知道向上转换被认为是“安全的”,但是当继承是虚拟的时,编译器如何知道编译时基本子对象的偏移量? static_cast 使用 vtable 吗?

当我们有这样的东西时,这尤其令人困惑(注意它不是虚拟的):

class Third : public Derived {...};

...

Derived *d = new Third();            // non-virtual upcast, no offset will be added
Base *b = static_cast<Base*>(d);

这次我使用了相同的static_cast 行,但是Base 子对象的偏移量不同!

对象的内存布局:

[ derived part | third part | base part ]

那么如何在编译时确定,如果取决于d指向的对象的实际动态类型呢?

【问题讨论】:

  • 非常有趣的问题;我希望有更详细的问题

标签: c++ oop virtual-inheritance static-cast


【解决方案1】:

当您有一个指向Derived 的指针时,很清楚要使用哪个Base,您甚至可以将指向Derived 的指针隐式转换为指向Base 的指针!如果需要任何地址调整,编译器将弄清楚如何使用嵌入式指针、vtable 或其他方式进行调整:C++ 标准没有规定确切的方法。具体做什么取决于 ABI。例如,对于Itanium C++ ABI,虚拟基础的偏移量似乎存储在虚拟表中。

【讨论】:

  • 据我所知,通常情况下,偏移量存储在 vtable 中。然而,这并没有回答它是如何在编译时静态完成的问题。如果您查看我提供的两种情况,就会提出哪个 vtable 具有正确偏移量的问题?编译器应该看哪一个,Derived 的 vtable 还是 Third 的 vtable?显然,vtable 中的 2 个偏移量是不同的,选择正确的 vtable 取决于 d 的运行时类型。这就是为什么我无法理解它是如何静态完成的。
  • static_cast 中的“静态”并不意味着它是在编译时完成的!它只是意味着编译器可以在编译时静态地找出在哪里找到信息:例如,它知道在哪里查找 vtable 中的偏移量或指向基址的嵌入指针的位置(取决于虚拟继承的方式)已实施)。它不会像 dynamic_cast 那样在 vtable 中寻找某个类的匹配项。
  • 所以你说 static_cast 有一些动态方面,我明白了。按照这个逻辑,为什么 static_cast 不能在虚拟继承中进行向下转换?
  • 基类不知道它被用作虚拟基类,即它没有虚拟表指针!但是,派生类现在确实涉及到虚拟继承,并且它确实具有虚拟表指针(并且涉及虚拟基类的完整对象可能具有多个虚拟表指针)。
猜你喜欢
  • 1970-01-01
  • 2011-10-03
  • 2013-12-18
  • 1970-01-01
  • 2016-10-26
  • 2013-08-24
  • 1970-01-01
相关资源
最近更新 更多