dynamic_cast changed behavior in VS5
-
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 castDerivedClass
toBaseClass
: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 thatDerivedClass
definition is equal to:class DerivedClass : **private** BaseClass { ... };
Which means thatDerivedClass
cannot be cast toBaseClass
. 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 theBaseClass
successfully at run-time andb
will be a valid pointer. When this code is compiled with Visual Studio 2005,b
will beNULL
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. -
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 castDerivedClass
toBaseClass
: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 thatDerivedClass
definition is equal to:class DerivedClass : **private** BaseClass { ... };
Which means thatDerivedClass
cannot be cast toBaseClass
. 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 theBaseClass
successfully at run-time andb
will be a valid pointer. When this code is compiled with Visual Studio 2005,b
will beNULL
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.I think that you had that problem because VS2005 is supposed to be more compatible with the ansi c++ standards, and by default, base classes specified in "class" are private and base classes specified in "struct" are public. Best regards, Mauro H. Leggieri
-
I think that you had that problem because VS2005 is supposed to be more compatible with the ansi c++ standards, and by default, base classes specified in "class" are private and base classes specified in "struct" are public. Best regards, Mauro H. Leggieri
-
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 castDerivedClass
toBaseClass
: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 thatDerivedClass
definition is equal to:class DerivedClass : **private** BaseClass { ... };
Which means thatDerivedClass
cannot be cast toBaseClass
. 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 theBaseClass
successfully at run-time andb
will be a valid pointer. When this code is compiled with Visual Studio 2005,b
will beNULL
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.You should derive this class in this way
class DerivedClass : public BaseClass { ... };
By default, the inheritance of 'class' symbols are private and, according to C++ standard, the derived class is not a sublass of its privately inherited superclass. In different words, private inhertance is the inheritance of the base class' implementation and public inheritance is the inheritance of the base class' interface. -
You should derive this class in this way
class DerivedClass : public BaseClass { ... };
By default, the inheritance of 'class' symbols are private and, according to C++ standard, the derived class is not a sublass of its privately inherited superclass. In different words, private inhertance is the inheritance of the base class' implementation and public inheritance is the inheritance of the base class' interface. -
Sorry, i've missed the second half of your posting. Anyway, the old behaviour should be considered as a bug, not a new one.
-
Sorry, i've missed the second half of your posting. Anyway, the old behaviour should be considered as a bug, not a new one.