how does c++ multiple inheritance casting work?

只谈情不闲聊 提交于 2021-02-05 06:00:16

问题


This question helped me to understand a bit, but my question is slightly different from theirs.

Basic typecasting as I understand it in c++ involves reinterpreting a structure in memory, as a different structure. For example:

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;
};

The critical point here is that an Office can be interpreted in memory as a Building without any changes to the structure. This breaks down in the multiple inheritance case:

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;
}

It is not possible to interpret amph as both a LandDweller and a WaterDweller without reorganizing the Amphibian structure in memory. How do those casts work, assuming they have any useful meaning? If not, Would static_cast, dynamic_cast, or reinterpret_cast be appropriate here?

EDIT: Thank you very much for the answer Sneftel. The TinyDr link you provided in one of your comments was very helpful, and the advice to avoid c-style casts is some I will take to heart.

For those that are curious, here are the pointers I got when I tried running this code:

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

You can see here that even though Land and Water Dwellers inherit from the same base class, they include their own copies of it as if the base classes were different. This leads to the Diamond Problem mentioned by Sneftel in his comments.


回答1:


If you look at the address stored in land, you'll notice that it's a higher number than amph. That's because, in C++, casts can end up doing pointer arithmetic as part of their internal operation. Amphibian has a WaterDweller in it, and a LandDweller after that. When casting to a base type whose data doesn't start at the beginning of the derived class, the pointer is adjusted to where that base class's data starts.

Incidentaly, take Dieter's advice, and don't use C-style casts in C++ (particularly for pointer types). The behavior of C-style casts in C++ is a mishmash of static_cast, reinterpret_cast, and const_cast, and it's easy to end up doing something different than you intended, without so much as a compiler warning. Best to make the type of casting you're doing explicit.



来源:https://stackoverflow.com/questions/21838382/how-does-c-multiple-inheritance-casting-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!