是否将reinterpret_cast的派生类指针转换为基类指针未定义的行为? [英] Is converting a reinterpret_cast'd derived class pointer to base class pointer undefined behavior?

查看:96
本文介绍了是否将reinterpret_cast的派生类指针转换为基类指针未定义的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看一个简单的例子:

struct Base { /* some virtual functions here */ };
struct A: Base { /* members, overridden virtual functions */ };
struct B: Base { /* members, overridden virtual functions */ };

void fn() {
    A a;
    Base *base = &a;
    B *b = reinterpret_cast<B *>(base);
    Base *x = b;
    // use x here, call virtual functions on it
}

这个小片段是否有未定义的行为?

Does this little snippet have Undefined Behavior?

reinterpret_cast的定义很明确,它返回的值base不变,只是类型为B *.

The reinterpret_cast is well defined, it returns an unchanged value of base, just with the type of B *.

但是我不确定Base *x = b;行.它使用类型为B *b,但实际上它指向A对象.而且我不确定x是否是适当的" Base指针,是否可以使用它调用虚拟函数.

But I'm not sure about the Base *x = b; line. It uses b, which has a type of B *, but it actually points to an A object. And I'm not sure, whether x is a "proper" Base pointer, whether virtual functions can be called with it.

推荐答案

static_cast(或隐式派生到基址指针的转换,其作用完全相同)与reinterpret_cast有很大不同.不能保证基础子对象的起始地址与完整对象的地址相同.

static_cast (or an implicit derived-to-base-pointer conversion, which does exactly the same thing) is substantially different from reinterpret_cast. There is no guarantee that that the base subobject starts at the same address as the complete object.

大多数实现将 first 基础子对象放置在与完整对象相同的地址上,但是当然,即使这样的实现也不能将两个不同的非空基础子对象放置在同一位置.相同的地址. (具有虚拟功能的对象不能为空).如果基础子对象与完整对象不在同一地址,则static_cast不是空操作,它涉及指针调整.

Most implementations place the first base subobject at the same address as the complete object, but of course even such implementations cannot place two different non-empty base subobjects at the same address. (An object with virtual functions is not empty). When the base subobject is not at the same address as the complete object, static_cast is not a no-op, it involves pointer adjustment.

有些实现甚至从未将第一个基础子对象放置在与完整对象相同的地址上.例如,允许将基础子对象放置在所有派生成员之后. IIRC Sun C ++编译器用于以这种方式布局类(不知道它是否仍在这样做).在这样的实现中,几乎可以保证该代码将失败.

There are implementations that never place even the first base subobject at the same address as the complete object. It is allowed to place the base subobject after all members of derived, for example. IIRC the Sun C++ compiler used to layout classes this way (don't know if it's still doing that). On such an implementation, this code is almost guaranteed to fail.

具有多个基数的B的相似代码将在许多实现中失败. 示例.

Similar code with B having more than one base will fail on many implementations. Example.

这篇关于是否将reinterpret_cast的派生类指针转换为基类指针未定义的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆