是否有定义向下转换实际Base到Derived的情况? [英] Are there cases where downcasting an actual Base to a Derived would be defined?

查看:239
本文介绍了是否有定义向下转换实际Base到Derived的情况?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一般情况下,它是一个非常好的应用程序未定义从一个(动态)基本到一个派生类派生

In the general case, it is (a very well deserved) Undefined Behavior to dowcast from a (dynamic) Base to one of the deriving classes Derived

class Base
{
public:
    virtual void foo()
    { /* does something */ }

    int a;
}

class Derived : public Base
{
public:
    virtual void foo()
    { /* does something different */ }

    double b;
}

Base obj;
Derived derObj = *static_cast<Derived *>(&obj);  // <- here come the demons

在当前的编译器实现方法中,至少是V表中不一致的值的问题,b包含垃圾值。所以标准没有定义这些条件下的downcast的行为是有道理的。

In the current implementation approach of compilers, here there would obviously be at least the problems of inconsistent values in the Vtable and b containing garbage values. So it makes sense the standard does not define the behavior of a downcast in those conditions.

但我很想知道如果在特定情况下对此规则有一些让步?
例如:

Yet I was curious to know if there were some concessions to this rule in specific cases ? For an example :

class Base
{
public:
    void foo()
    { /* does something */ }

    int a = 1;
    double b = 2.;
}

class DerivedForInt : public Base
{
    int getVal()
    { return a }
}

Base obj;
DerivedForInt derObj = *static_cast<DerivedForInt *>(&obj);  // <- still an UB ?

这里我们可以轻松地想象编译器做正确的事情。 但从标准的角度来看,是否仍然未定义?

Here we can easily imagine compiler doing the right thing. But from the standard perspective, is it still undefined ?

编辑: static_cast ,如果与其他演员一起工作也很有趣!

Edit : static_cast is a random choice for illustration purpose, it is also interesting if working with other casts !

推荐答案

..

显然,正如其他答案所说,这是未定义的行为,在标准中发现。但是,如果 Base 类具有标准布局,而您的 DerivedForInt 类不会添加新数据

Obviously, as the other answers stated this is undefined behaviour, as found in the standard. But if your Base class has standard layout and your DerivedForInt class does not add new data members it will have the same (standard) layout.

在这些条件下,你的演员应该不会引起麻烦,即使是UB。根据其中一个来源,至少可以安全地做一个

Under these conditions your cast should cause no troubles even it being UB. According to one of the sources, it is at least safe to do a

DerivedForInt *derived = reinterpret_cast<DerivedForInt*>(&base.a);

资料来源:

什么是聚合和POD以及如何/为什么他们特别吗?

POD和C ++ 11中的继承。

从第二个链接:


以下是标准部分9 [class]的定义:

Here's the definition, from the standard section 9 [class]:


标准布局类是一个类:

A standard-layout class is a class that:


  • 没有类型为非标准布局类(或类型的数组)的非静态数据成员,参考

  • 没有虚拟函数(10.3)和虚拟基本类(10.1),

  • 具有相同的访问控制所有非静态数据成员,

  • 没有非标准布局基类,

  • 在最多不包含非静态数据成员派生类和至多一个具有非静态数据成员的基类,或者没有具有非静态数据成员的基类,并且

  • 没有与第一个类型相同的基类非静态数据成员。

  • has no non-static data members of type non-standard-layout class (or array of such types) or reference,
  • has no virtual functions (10.3) and no virtual base classes (10.1),
  • has the same access control (Clause 11) for all non-static data members,
  • has no non-standard-layout base classes,
  • either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
  • has no base classes of the same type as the first non-static data member.

.mem]):


指向使用reinterpret_cast适当转换的标准布局结构体对象的指针指向其初始成员

A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa.

这实际上比它更好,因为它是位字段,而不是它所在的单元。旧的要求,因为reinterpret_cast的能力不会因添加非平凡的构造函数和/或析构函数而丢失。

This is actually better than the old requirement, because the ability to reinterpret_cast isn't lost by adding non-trivial constructors and/or destructor.

这篇关于是否有定义向下转换实际Base到Derived的情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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