Ok, so first up is question 1.
1.1) typeid(*a); is well formed. It will return the typeid of SubBase2.
1.2) dynamic_cast(a); is well formed as well, as a is of type Base* and SubBase2 is derived from Base. Results in a SubBase2*.
1.3) typeid(*b); is malformed and results in undefined behavior. Since we are in the constructor of SubBase2, type SubBase1 is not a base of SubType2.
1.4) dynamic_cast(b); is malformed and results in undefined behavior. Since we are in the constructor of SubBase2, type SubBase1 is not a base of SubType2
1.5) a->Arr(); Well formed, calls SubBase2::Arr().
1.6) b->Arr(); Malformed, undefined behavior. SubBase1 is not a base of SubBase2.
This example was almost an exact copy of two similar examples from the standard, in section 12.7. When typeid or dynamic_cast is used in a constructor or in a destructor, or in a function called from either, and if the operator of typeid/dynamic_cast refers to the object under construction or destruction, and the static type of the operand is neither the constructor nor the destructors class, nor one of its bases, then the behavior is undefined.
Question 2:
2.1) X* p; Is well formed, pointers to incomplete types are allowed.
2.2) X a; Is malformed, this results in infinite recursion and hence the result is undefined behavior.
This one was an exact copy of the standard, from section: 14.7.1 -14.
It's not really all that surprising that such detail isn't typically known to people. However, it is these details that tend to nail people in the end. Especially of concern are constructors and destructors. These member functions of classes behave differently than all other member functions, and as such the rules of their behavior should be well understood before hand.
I've got a question though... You (as well as others) refer to the C++ standard (presumably the latest ISO one?). Have you got this in print form, or are you looking it up online?
Just wondering if it's a reference I should add to my list of things-to-buy [smile]
cheers,
Jack