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
C
that 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
A
has 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
.