【问题标题】:How safe is it to assume that a derived class's pointer is the same as the first base class's pointer?假设派生类的指针与第一个基类的指针相同有多安全?
【发布时间】:2020-11-25 03:09:27
【问题描述】:

考虑这个程序:

struct Base1 { void *x; virtual ~Base1() { } };
struct Base2 { void *x; virtual ~Base2() { } };

struct Derived : Base1, Base2 { };

int main()
{
    Derived d;
    return &d == static_cast<void *>(static_cast<Base1 *>(&d));
}

在我对 Clang、GCC 和 Visual C++ 的所有测试中,返回值为 1

我知道 C++ 实际上并不能保证这一点。

但是,实际上,这可靠吗?
(假设没有虚拟继承。编辑:我假设多态基类。)

在哪些实际情况(如果有的话)中,指向派生类的指针需要调整才能用作指向其第一个(非虚拟、多态)基类的指针?

【问题讨论】:

  • @user541686 不适用于给定的示例,但与Mismatch of 'this' address when base class is not polymorphic but derived is有些相关。
  • @user541686 这是一个有趣的问题,但没有明确的答案。我可以说,据我所知,这适用于直到上周的所有 MSVC 版本,但即使这样也没有说明下一次更新,因为该行为不是标准规定的。或者您可以将其标记为compiler-construction,但这可能会引起所有常见假设都被打破的假设实现的答案。只是好奇,是否有实际背景或问题引发了这个问题?
  • @dxiv:(谢天谢地?)下一个编译器版本不能随意破坏它,因为它会破坏 ABI 与现有二进制文件的兼容性,人们会变得非常难过。在任何情况下,使用断言或其他东西在代码中测试这一点很容易,以捕捉潜在的未来破坏,所以我不担心未来的变化。主要是问现状。是的,它基于一个实际问题——我试图“取消模板化”一些代码,然后意识到这样做(至少以我尝试的方式)将依赖于这个假设是正确的。
  • @user541686 众所周知,MSVC(实际上是documented)会破坏版本之间的 ABI,尽管不一定是布局基础。绑定到Itanium C++ ABI(包括gcc)的编译器可能满足这个假设,尽管我还没有阅读规范页面的最后细节。即便如此,这并不能开始回答一般问题。
  • @dxiv:是的,我意识到并非每个 ABI 都是一成不变的,但这种 类型的ABI 看起来确实如此。它不仅会破坏与旧 CRT 接口的东西,还会破坏世界上编写代码的各种 Windows ABI(包括 COM 等)。他们唯一能做的就是引入一种“新”类型的类或继承机制,以保持旧的完整。我的意思是理论上是可能的,但是……老实说,我并不担心。事实上,由于 Windows 标头中的 C 接口代码,整个 vtable 布局现在可能已经一成不变。

标签: c++ inheritance vtable


【解决方案1】:

我可以想到编译器(或链接器,如果使用-flto)理论上可能会打乱类中基类的顺序的原因。如果Base2 的使用次数多于Base1,它可能会认为这是一个优化机会。

我认为这绝不可能,但有可能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-15
    • 2013-03-04
    • 1970-01-01
    • 2021-09-09
    相关资源
    最近更新 更多