简体   繁体   English

错误的演员表 - 是演员表或使用未定义的行为

[英]Incorrect cast - is it the cast or the use which is undefined behavior

If I do a cast from a Base to a Derived type, but the Base type isn't an instance of derived type, but only use the result if it is, do I get undefined behaviour? 如果我从Base转换为Derived类型,但Base类型不是派生类型的实例,但只使用结果,是否会得到未定义的行为?

Hard to understand what I'm asking? 很难理解我在问什么? take a look at this example: 看看这个例子:

struct Animal { int GetType(){...} };
struct Dog : Animal { bool HasLoudBark(){...}};
struct Cat : Animal { bool HasEvilStare(){...} };

Animal * a = ...;
Dog* d = static_cast<Dog*>(a);

if(a->GetType() == DogType && d->HasLoudBark())
    ....

In this case a may or not be a Dog . 在这种情况下a可能是或不是Dog We always do the static_cast of a to Dog * d but we never use d unless we're sure its a Dog . 我们总是做static_castaDog * d ,但我们从来没有使用d ,除非我们确定它是一个Dog

Assuming that a is not a Dog , is this undefined behaviour at the point of the cast? 假设a不是Dog ,那么这个未定义的行为是否在演员阵容中? Or is it defined as we don't actually use d unless it is really is a Dog ? 或者它被定义为我们实际上不使用d除非它真的是一只Dog

References to the relevant parts of the standard are appreciated. 赞赏参考标准的相关部分。

(Yes I know I can use dynamic_cast, and RTTI, and probably this isn't great code, but I'm more interested in whether this is valid) (是的,我知道我可以使用dynamic_cast和RTTI,可能这不是很好的代码,但我对这是否有效更感兴趣)

The cast itself has undefined behaviour. 演员本身有不确定的行为。 Quoting C++17 (n4659) [expr.static.cast] 8.2.10/11: 引用C ++ 17(n4659)[expr.static.cast] 8.2.10 / 11:

A prvalue of type “pointer to cv1 B ”, where B is a class type, can be converted to a prvalue of type “pointer to cv2 D ”, where D is a class derived (Clause 13) from B , if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1 . 类型为“指向cv1 B指针”的prvalue,其中B是类类型,可以转换为类型为“指向cv2 D指针”的prvalue,其中D是从B派生的类(第13条),如果cv2是与cv1相同的cv资格,或更高的cv资格。 ... If the prvalue of type “pointer to cv1 B ” points to a B that is actually a subobject of an object of type D , the resulting pointer points to the enclosing object of type D . ...如果类型“指针CV1的prvalue B ”指向一个B实际上是类型的对象的子对象D ,将所得指针指向类型的包围对象D Otherwise, the behavior is undefined. 否则,行为未定义。

This is undefined behaviour , but (funny enough) if you would have used reinterpret_cast instead of static_cast , you would cast that demon away. 这是未定义的行为 ,但是(有趣的是)如果您使用reinterpret_cast而不是static_cast ,则会将该恶魔抛弃。

[expr.reinterpret.cast]/7

An object pointer can be explicitly converted to an object pointer of a different type. 可以将对象指针显式转换为不同类型的对象指针。 When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T ”, the result is static_cast<cv T*>(static_cast<cv void*>(v)) . 当对象指针类型的prvalue v被转换为对象指针类型“指向cv T指针”时,结果是static_cast<cv T*>(static_cast<cv void*>(v))

As noted by user Angew, this "requires a particular internal representation which ensures that static_cast<void*>(d) == static_cast<void*>(a) when a == d ". 正如用户Angew所指出的,这“需要一个特定的内部表示,以确保static_cast<void*>(d) == static_cast<void*>(a)a == d ”时。

This is expressed by [class.mem]/22 to 26 : 这由[class.mem]/2226

[class.mem]/26

If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member if that member is not a bit-field. 如果标准布局类对象具有任何非静态数据成员,则其地址与其第一个非静态数据成员的地址相同(如果该成员不是位字段)。 Its address is also the same as the address of each of its base class subobjects. 它的地址也与每个基类子对象的地址相同。

So if GetType() of Animal returns the value of a non-static data member from the common initial sequence of Animal and Dog , the behavior is defined. 因此,如果Animal GetType()AnimalDog公共初始序列返回非静态数据成员的值,则定义行为。

Those requirements are met when dealing with simple inheritance and default-aligned objects. 处理简单继承和默认对齐对象时,满足这些要求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM