【问题标题】:Does void* reserve inheritance information?void* 是否保留继承信息?
【发布时间】:2017-04-20 14:08:53
【问题描述】:

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* 真的记得类型吗?
它能“记住”多远?

背景

我正在尝试创建一个 void* 抽象类 here,但很惊讶它可以工作。
我想确保这是预期的标准行为。

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

【问题讨论】:

  • 通过使用static_cast,您是在告诉它的类型。如果您改为告诉它一些完全不相关的类型,它甚至可能似乎工作。它只是下面的字节,以不同的方式解释。 (不过应该是Undefined Behaviour)。
  • 只有当v 指向C 时,强制转换才有效,而它恰好是这样做的。 bvc 恰好都指向同一个地址。当您使用多重继承时,情况并非总是如此,并且强制转换会产生无效的指针。
  • @BoBTFish 但我已经说明它是“C*”,而不是“B*”。
  • 您创建了一个new C,因此在指针的另一端是C 对象的有效字节表示。为什么你会惊讶于说“在这个指针的末尾是一个C”(即`static_cast)你得到了预期的值?

标签: c++ c++14 void-pointers static-cast


【解决方案1】:

未定义的行为是未定义的。这意味着您可能,只是可能,无论如何都会得到“正确答案”。

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

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

这不是您可以依赖的。这只是一个“幸运”的偶然事件。


它是指向 C 的指针,然后是指向 B 的指针,然后是指向 void 的指针,然后又是指向 C 的指针。所有完全合法的转换。

不,他们不是。

它是一个指向C 的指针,然后是一个指向B 的指针。然后它变成void*。但标准非常明确:如果您将指针转换为void*唯一合法的转换是将其转换为指向确切类型的指针投自。因此,如果您从B* 转换为void*,则唯一合法的转换是返回B*

不是从B派生的类型。

C++17 将“确切类型”变为“指针可互转换类型”。但是基类和派生类不是指针互转换的,所以它仍然是 UB。

【讨论】:

  • 知道了。是的,您在备份的路上绝对需要通过B*
  • @NicolBolas:可否添加相关的标准段落?
  • 你能修改我的代码吗?我随机尝试向这两个类添加更多字段,但它仍然有效。
  • @javaLover 有 C 继承自 B 之前的非空类。
  • @VittorioRomeo:这是多种事物的结合。 [expr.static.cast]/13 解释了static_cast 的行为,对于转换为错误的类型,它只是说指针值不变;它特别地并没有说它是一个指向C 类型对象的指针。通过C 类型的指针访问B 类型的对象的未定义行为是通过[basic.lval]/8 处理的。
【解决方案2】:

(Nicol 是正确的;我的回答更入门,不涉及语言律师;不过,您应该会发现它与您在现实中的观察充分匹配。)


我希望 c 指向 B* 的地址

确实如此。

(地址错误)

不,这是正确的地址。

但它似乎知道 v 是 B* 并且正确转换。

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

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

您的void* 什么都不记得了;所有这些“智能”都存在于BC 的定义中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-14
    • 2019-08-03
    • 1970-01-01
    • 2021-07-05
    相关资源
    最近更新 更多