c ++多重继承转换如何工作?

时间:2014-02-17 20:10:12

标签: c++ inheritance casting

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解释为WaterDwellerAmphibian假设它们有任何有用的含义,这些演员如何运作?如果没有,那么static_castdynamic_castreinterpret_cast是否合适?

编辑:非常感谢Sneftel的回答。你在其中一条评论中提供的TinyDr link非常有用,而且我会考虑一些避免c风格演员的建议。

对于那些好奇的人,这是我在尝试运行此代码时得到的指示:

land 0x22c8018
sea 0x22c8010
run 0x22c801c
swim 0x22c8014
land alive 0x22c8018
sea alive 0x22c8010

你可以在这里看到,即使Land and Water Dwellers继承自同一个基类,它们也包含它们自己的副本,就像基类不同一样。这导致了Sneftel在他的评论中提到的钻石问题。

1 个答案:

答案 0 :(得分:3)

如果您查看land中存储的地址,您会发现它的数字高于amph。这是因为,在C ++中,强制转换最终可以将指针算法作为其内部操作的一部分。 Amphibian中包含WaterDweller,之后有LandDweller。当转换为其数据未在派生类的开头开始的基类型时,指针将调整到该基类的数据开始的位置。

顺便提一下,请考虑Dieter的建议,不要在C ++中使用C风格的强制转换(特别是对于指针类型)。在C ++中C风格的强制转换的行为是static_castreinterpret_castconst_cast的混合,并且很容易最终做出与你想要的不同的东西,而不是一个编译警告。最好制作明确的铸造类型。