如果我从Base转换为Derived类型,但Base类型不是派生类型的实例,但只使用结果,是否会得到未定义的行为?
很难理解我在问什么?看一下这个例子:
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())
....
在这种情况下,a
可能是Dog
,也可能不是static_cast
。我们总是a
Dog * d
到d
,但除非我们确定Dog
,否则我们永远不会使用a
。
假设Dog
不是d
,那么在演员阵容中这个未定义的行为是什么?或者它定义为我们实际上不使用Dog
,除非它真的是 Sub S
Dim ws as worksheet
For each ws in worksheets
ws.calculate
'or call your recalc routine
ws.printout
next ws
end sub
?
赞赏参考标准的相关部分。
(是的,我知道我可以使用dynamic_cast和RTTI,可能这不是很好的代码,但我对这是否有效更感兴趣)
答案 0 :(得分:36)
演员本身有不确定的行为。引用C ++ 17(n4659)[expr.static.cast] 8.2.10 / 11:
类型为“指向 cv1
B
的指针”的prvalue,其中B
是类类型,可以转换为类型为“指针”的prvalue 到 cv2D
“,其中D
是B
派生的类(第13条),如果 cv2 是相同的cv - 资格为或更高 cv-qualification, cv1 。 ......如果是prvalue 键入“指向 cv1B
的指针”指向B
,它实际上是D
类型对象的子对象,结果指针 指向D
类型的封闭对象。否则,行为未定义。
答案 1 :(得分:12)
This is undefined behaviour,但(足够有趣)如果您使用static_cast
而不是cv T
,则会将该恶魔赶走。
可以将对象指针显式转换为不同类型的对象指针。当对象指针类型的prvalue v转换为对象指针类型“指向
static_cast<cv T*>(static_cast<cv void*>(v))
的指针”时,结果为static_cast<void*>(d) == static_cast<void*>(a)
。
正如用户Angew所说,这个&#34;需要一个特定的内部表示,以确保a == d
&#34;时的[class.mem]/22
。
这由26
表示为GetType()
:
如果标准布局类对象具有任何非静态数据成员,则其地址与其第一个非静态数据成员的地址相同(如果该成员不是位字段)。它的地址也与每个基类子对象的地址相同。
因此,如果Animal
的{{1}}返回Animal
Dog
和/queue
的非静态数据成员的值,则会定义行为
在处理简单继承和默认对齐的对象时,会满足这些要求。