I know that it's legal to use dynamic_cast to do a "cross-cast" across a class hierarchy. For example, if I have classes that look like this:
A B
\ /
C
If I have an A* pointer that's pointing at an object of type C, then I can use
A* aPtr = /* ... something that produces a C* ... */
B* bPtr = dynamic_cast<B*>(aPtr);
to get a pointer to the B base object of the C I'm pointing at.
The reason I mention this is that at the time that I write the above code, it's possible that the compiler has not yet seen the definition of C even though it's seen A and B. This means that it's possible that the compiler does not detect any sort of connection between A and B, but it still has to compile the code anyway because it's possible for a class like C to exist and for the dynamic_cast to succeed under some circumstance.
The problem is that this means that I can accidentally cross-cast to an object of the wrong type. Suppose that I have classes that look like this:
A B D
\ /
C
Here, D is some random unrelated class. If I try writing something like this:
A* aPtr = /* ... get a C* pointer ... */
D* dPtr = dynamic_cast<D*>(aPtr);
Then this dynamic_cast will always fail at runtime, since there's no possible way to connect A and D. If I'm using D accidentally because I meant to use B, the compiler will give me no indication whatsoever that I have a meaningless cast.
My question is: is there some way that I can get the compiler to warn me that the cast will always fail at runtime? I'd be happy with a language-level solution or some compiler setting for any major compiler that could detect this. If there's an external tool, that's fine as well; I just want to know if it's possible to catch this class of errors.
It's not possible to detect this at compile-time. The class
Cthat introduces the relationship could be found in a dynamically loadable library that hasn't even been written yet, and the compiler can't prove otherwise.There may be a few exceptions though. If
Ahas only private constructors (or a private destructor) then the compiler can be certain that there will be no new subclasses that aren't named as friends byA.