jav*_*ver 0 c++ void-pointers static-cast c++14
是否有可能void*保留类型信息?
我试图使它忘记了真正的类型(B*)通过投B* b来void* v,但它似乎知道它的起源.
这对我来说是好运,但我不知道为什么.
这是一个简化的代码(完整演示): -
#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;
}
Run Code Online (Sandbox Code Playgroud)
我希望c指向B*(一个错误的地址)的地址,但似乎知道这v是B*正确的.
它为什么有效?难道void*真的记得类型?
它能"记住"多远?
我试图在这里创建一个void*抽象类,但惊讶它的工作原理.
我想确保它是一个预期的标准行为.
编辑:抱歉新手问题.
现在,我意识到我误解了void*.
未定义的行为未定义.这意味着无论如何你可能会得到"正确答案".
在这种特殊情况下,编译器的布局完全有可能组织起来C,C并且它的基类B具有相同的地址.因此,如果你假装一个是以未定义的方式指向另一个的指针,那么你会得到正确的行为.
今天.明天会发生什么是猜测.
这不是你可以依赖的东西.这只是一个"幸运"的偶然事件.
它是指向C的指针,然后是指向B的指针,然后是指向void的指针,然后是指向C的指针.所有完全合法的转换.
不,他们不是.
它是一个指针C,然后指向B.然后它变成了void*.但标准非常明确:如果将指针转换为a void*,则唯一合法的转换是将其转换为指向从中转换的确切类型的指针.因此,如果您转换B*为void*,则唯一的合法转换将返回B*.
不是来自的类型B.
C++ 17将"确切类型"变成"指针可互换类型".但是基类和派生类不是指针可互换的,所以它仍然是UB.