[英]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_cast
的a
对Dog * 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
”, whereB
is a class type, can be converted to a prvalue of type “pointer to cv2D
”, whereD
is a class derived (Clause 13) fromB
, if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1 .类型为“指向cv1
B
指针”的prvalue,其中B
是类类型,可以转换为类型为“指向cv2D
指针”的prvalue,其中D
是从B
派生的类(第13条),如果cv2是与cv1相同的cv资格,或更高的cv资格。 ... If the prvalue of type “pointer to cv1B
” points to aB
that is actually a subobject of an object of typeD
, the resulting pointer points to the enclosing object of typeD
....如果类型“指针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
,则会将该恶魔抛弃。
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 isstatic_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]/22
到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()
从Animal
和Dog
的公共初始序列返回非静态数据成员的值,则定义行为。
Those requirements are met when dealing with simple inheritance and default-aligned objects. 处理简单继承和默认对齐对象时,满足这些要求。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.