If A and B are a verbatim copy of each other (except for their names) and are declared in the same context (same namespace, same #defines, no __LINE__ usage), then common C++ compilers (gcc, clang) will produce two binary representations which are fully interchangeable.
If A and B use the same method signatures but the bodies of corresponding methods differ, it is unsafe to cast A* to B* because the optimization pass in the compiler could for example partially inline the body of void B::method() at the call site b->method() while the programmer's assumption could be that b->method() will call A::method(). Therefore, as soon as the programmer uses an optimizing compiler the behavior of accessing A through type B* becomes undefined.
Problem: All compilers are always at least to some extent "optimizing" the source code passed to them, even at -O0. In cases of behavior not mandated by the C++ standard (that is: undefined behavior), the compiler's implicit assumptions - when all optimizations are turned off - might differ from programmer's assumptions. The implicit assumptions have been made by the developers of the compiler.
Conclusion: If the programmer is able to avoid using an optimizing compiler then it is safe to access A via B*. The only issue such a programmer needs to tackle with is that non-optimizing compilers do not exist.
A managed C++ implementation might abort the program when A* is casted to B* via reinterpret_cast, when b->field is accessed, or when b->method() is called. Some other managed C++ implementation might try harder to avoid a program crash and so it will resort to temporary duck typing when it sees the program accessing A via B*.
Some questions are:
- Can the programmer guess what the managed C++ implementation will do in cases of behavior not mandated by the C++ standard?
- What if the programmer sends the code to another programmer who will pass it to a different managed C++ implementation?
- If a case isn't covered by the C++ standard, does it mean that a C++ implementation can choose to do anything it considers appropriate in order to cope with the case?
bto call virtual functions or useBonly members will definitely lead to UB. Thinkxis safe though.xis safe though" true or not. I have a feeling, that while this seems harmless (it's a no-op) at the first sight, it is UB.reinterpret_castcannot safely convert between base and derived class pointers/references.bis not guaranteed to be a valid pointer. The only safe thing you can do with it is reinterpret_cast it back to the original type.bwithreinterpret_cast. It should give you a properBasepointer. Now, thatreinterpret_castis nothing else, than a conversion tovoid *, then toBase *. My example code does something similar (it just doesn't have the conversion tovoid *, and the conversion toBase *is implicit, not throughstatic_cast). Anyways, I'm just playing the devil's advocate here. I have an insight that the conversion is UB, but cannot backup this with the standard.The result of the conversion is a pointer to the base class subobject of the derived class object.(timsong-cpp.github.io/cppwp/conv.ptr#3), means that we have indeed dereferencedband so hit UB.