问题
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