C-Style upcast and downcast involving private inheritance

杀马特。学长 韩版系。学妹 提交于 2019-12-18 04:55:17

问题


Consider the following piece of code :-

class A {};

class B : private A {};

B* bPtr1 = new B;
// A* aPtr1 = bPtr1; // error
// A* aPtr2 = static_cast<A*>(bPtr1); // error
A* aPtr3 = (A*)bPtr1;
B* bPtr2 = (B*)aPtr3;

The C-style cast discards the private inheritance while both the implicit and static_cast fail (also dynamic_cast). Why ? If C-style casts are just bit-fiddling, how are C++ casts implemented i.e. how do they know the type of inheritance from memory footprint?

After bPtr1 is casted to aPtr3, i will have to use another C-style cast to downcast to B as again both static_cast and dynamic_cast fail. So, is bPtr2 guaranteed to be good?

Thanks in advance


回答1:


The standard states in 5.4.7 that C-style casts can actually do more than any sequence of new-style casts can do -- specifically including casting from a pointer-to-derived to pointer-to-base even when the base class is inaccessible, which is precisely what happens here with private inheritance. (Why this should be allowed, and in particular why it should be allowed only for C-style casts, is utterly beyond me; but it's undeniably allowed.)

So dribeas is right, compilers are obliged to handle the OP's C-style pointer conversion correctly, even when B inherits from multiple base classes. My own testing with MSVC++8 and MinGW confirms his results in practice -- when B inherits from multiple base classes, the compiler will adjust pointers when converting a B* to an A* or vice versa so that the correct object or subobject is identified.

I stand by my assertion that you ought to derive B publicly from A if you ever intend to treat a B as an A, since using private inheritance instead necessitates using C-style casts.




回答2:


The C++ casts are enforced by the compiler (not the linker). It's not that private inheritance causes a different class layout; it's that the compiler will forbid you from casting a pointer to a derived class to a pointer to its base class if the inheritance is not public, based on the declaration of the class.




回答3:


The existing answers are great, but one bit of information you may find helpful relates to this:

C-style casts are just bit-fiddling

If you use an old-style cast between two pointer types, the compiler usually wouldn't need to fiddle with any bits. You're telling the compiler that you want to treat a location of memory as if it contained some type (because you know that it effectively does), so the compiler does nothing at all at runtime to modify the contents of memory. Casting merely disables type safety at compile time.




回答4:


If C-style casts are just bit-fiddling, how are C++ casts implemented i.e. how do they know the type of inheritance from memory footprint?

C-style casts in C++ mean more than meets the eye. They are technically the only way to ask the compiler to choose the right cast operator required for conversion. For the same reason, this is better than using reinterpret_cast. The latter is implementation defined.

It seems there is a lot of confusion around C-style casts. Remember, no tool is safe until you know how to use it. The same applies to the C-style cast. The point of having a C-style cast is to ask the compiler to choose the safest and most portable conversion for a given pair of types. This may trigger a change from static_cast to reinterpret_cast silently and introduce errors. The point is: you need to know what you are doing.



来源:https://stackoverflow.com/questions/844816/c-style-upcast-and-downcast-involving-private-inheritance

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