void* 是否保留继承信息?

Does void* reserve inheritance information?

是否可以void*保留类型信息?
我试图通过将 B* b 转换为 void* v 来让它忘记真实类型 (B*),但它似乎知道它的来源。
这对我来说是好运,但我不知道为什么。

这是一个简化的代码(full demo) :-

#include <iostream>
#include <memory>
using namespace std;

class B{public: int ib=1;};
class C:public B{public: int ic=2;};

int main() {
    B* b=new C();
    void* v=b;                     //<- now you forget it!
    C* c=static_cast<C*>(v);    
    std::cout<<c->ib<<" "<<c->ic<<std::endl; //print 1 and 2 correct (it should not)
    return 0;
}

本以为c指向B*的地址(一个错误的地址),但似乎知道vB*并正确投射。

问题

为什么有效? void*真的记得类型吗?
它能走多远"remember"?

背景

我正在尝试创建一个 void* 摘要 class here,但很惊讶它的工作原理。
我想确保这是预期的标准行为。

编辑:抱歉新手问题。
现在,我意识到我误解了 void*.

未定义的行为是未定义。这意味着您可能 可能 ,无论如何都会得到 "right answer"。

在这种特殊情况下,您的编译器布局完全有可能组织 C,使得 C 及其基数 class B 具有相同的地址。因此,如果您假装一个以未定义的方式指向另一个,您将获得正确的行为。

今天。明天会发生什么是猜测。

这不是你可以依赖的东西。这只是一个 "fortunate" 偶然事件。


It's a pointer to C, then a pointer to B, then a pointer to void, then a pointer to C again. All perfectly legal conversions.

不,他们不是。

它是指向 C 的指针,然后是指向 B 的指针。然后就变成了void*。但标准非常明确:如果将指针转换为 void* 唯一合法的转换 是将其转换为指向 的指针type 从中投射出来的。所以如果你从 B* 转换成 void*,唯一合法的转换是回到 B*.

不是派生自 B 的类型。

C++17 将 "the exact type" 变为 "a pointer interconvertible type"。但是基础和派生 classes 是 not pointer-interconvertible,所以它仍然是 UB。

(Nicol 是正确的,我的回答是入门级的,没有涉及语言律师,不过,你应该会发现它与你在现实中的观察充分吻合。)


I expected c to point to the address of B*

确实如此。

(a wrong address)

不,这是正确的地址。

but it seems to know that v is B* and correctly cast.

它知道每个 C 都有一个 B 碱基。因为那是 C 的定义方式。

所以 C* 指向一个内存区域,其中包含一些 B 内容,然后是一些 C 内容。

你的 void* 什么都不记得了;所有这些 "intelligence" 都在 BC.

的定义中