Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking whether a cross-cast could possibly work?

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.

like image 509
templatetypedef Avatar asked Mar 16 '11 06:03

templatetypedef


1 Answers

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 by A.

like image 55
Ben Voigt Avatar answered Oct 05 '22 23:10

Ben Voigt