This question帮助我理解了一下,但我的问题与他们的问题略有不同。
我在c ++中理解的基本类型转换涉及将内存中的结构重新解释为不同的结构。例如:
class Building{int sqFootage;};
class Office : public Building{int cubicles;};
int main(int argc, char** argv){
Office *foo = new Office();
/*The cubicles member appears after the sqFootage member on an Office,
* so the foo pointer is really just a Building* with some extra
* information after it.
*/
Building *bar = (Building*)foo;
return 0;
};
这里的关键点是Office可以在内存中解释为建筑物,而不会对结构进行任何更改。这在多继承案例中分解:
class Animal{bool alive;};
class WaterDweller : public Animal{float swimSpeed;};
class LandDweller : public Animal{float runSpeed;};
class Amphibian : public WaterDweller, public LandDweller{float transitionSpeed};
int main(int argc, char** argv){
Amphibian *amph = new Amphibian();
LandDweller *land = (LandDweller*)amph;
WaterDweller *sea = (WaterDweller*)amph;
}
如果不重新组织内存中的amph
结构,则无法将LandDweller
解释为WaterDweller
和Amphibian
。 假设它们有任何有用的含义,这些演员如何运作?如果没有,那么static_cast
,dynamic_cast
或reinterpret_cast
是否合适?
对于那些好奇的人,这是我在尝试运行此代码时得到的指示:
land 0x22c8018
sea 0x22c8010
run 0x22c801c
swim 0x22c8014
land alive 0x22c8018
sea alive 0x22c8010
你可以在这里看到,即使Land and Water Dwellers继承自同一个基类,它们也包含它们自己的副本,就像基类不同一样。这导致了Sneftel在他的评论中提到的钻石问题。
答案 0 :(得分:3)
如果您查看land
中存储的地址,您会发现它的数字高于amph
。这是因为,在C ++中,强制转换最终可以将指针算法作为其内部操作的一部分。 Amphibian
中包含WaterDweller
,之后有LandDweller
。当转换为其数据未在派生类的开头开始的基类型时,指针将调整到该基类的数据开始的位置。
顺便提一下,请考虑Dieter的建议,不要在C ++中使用C风格的强制转换(特别是对于指针类型)。在C ++中C风格的强制转换的行为是static_cast
,reinterpret_cast
和const_cast
的混合,并且很容易最终做出与你想要的不同的东西,而不是一个编译警告。最好制作明确的铸造类型。