【发布时间】: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