I got into this case during migration of C++ code from VS03 to VS05. class BaseClass { ... }; class DerivedClass : BaseClass { ... };
Very simple code, when you'll try to cast DerivedClass
to BaseClass
: DerivedClass *d = new DerivedClass(); BaseClass *b = d;
The compiler will fail with an error. (Stop here and try to understand why) Gave up, the compiler will fail with and error: error C2243: 'type cast' : conversion from 'DerivedClass *' to 'BaseClass *' exists, but is inaccessible.
If you will try to do: DerivedClass *d = new DerivedClass(); BaseClass *b = dynamic_cast(d);
The compiler will show a warning: warning C4540: dynamic_cast used to convert to inaccessible or ambiguous base; run-time test will fail ('DerivedClass *' to 'BaseClass *')
The reason for this is that the default inheritance access is private, this means that DerivedClass
definition is equal to: class DerivedClass : **private** BaseClass { ... };
Which means that DerivedClass
cannot be cast to BaseClass
. To fix this we need to change the code and explicitly state that the derivation is public: class DerivedClass : **public** BaseClass { ... };
It is little complicated to show it here, but you can build a code that uses the dynamic_cast and doesn't show the warning or an error. It involves in using a dll that implements the classes, and an exe that uses these classes with forward declaration, and a virtual clone method, very ugly, but this is how our code is written. Now I am getting to the point. Assume you have code like the following, that doesn't show any error or warning during compilation. BaseClass *foo(DerivedClass *d) { BaseClass *b = dynamic_cast(d); return b; }
When this code is compiled with Visual Studio 2003, d
will be cast to the BaseClass
successfully at run-time and b
will be a valid pointer. When this code is compiled with Visual Studio 2005, b
will be NULL
at run-time. For years we didn't see that there was a missing 'public' in that inheritance, because everything worked. Note that the original application doesn't rely on the dynamic_cast, it only uses it in an assert statement to check that a casting is correct.