Condividi tramite


Breaking Changes in dynamic_cast 

In Microsoft Visual C++ 2005 as well as in Visual C++ .NET 2002, there were changes in the dynamic_cast operator, such that, the behavior of your application may change.

  • The Visual C++ 6.0 compiler allowed a runtime check to occur, when a compile-time check was required by the standard. This was fixed in Visual C++ .NET 2002 (Visual C++ 7.0).

  • The C runtime library now does a dynamic_cast runtime check to ensure the compile-time type of the expression being cast refers to a public base class sub-object of either the cast target type (for down-cast) or most-derived object type (for cross-cast).

For more information on compiler changes, see Breaking Changes in the Visual C++ Compiler.

Example

In this code sample, the variable pA2 is NULL in VC6; the compiler did not perform an identity check as specified in 5.2.7/3 in the ISO C++ Standard. However, this cast will succeed beginning in Visual C++ .NET 2002 (Visual C++ 7.0).

So, while this caused an exception to be thrown in Visual C++ 6.0, no exception in thrown now.

// dynamic_cast_breaking_change.cpp
struct A { 
   virtual void F() {}
};

struct B { 
   virtual void F() {}
};

void Test(A* pA) {
   A* pA2 = dynamic_cast<A*>(pA);
   A& rA = dynamic_cast<A&>(*pA);
}

int main() {
   B* pB = new B;
   Test(reinterpret_cast<A*>(pB));
}

Example

This sample shows that the C runtime library now does a dynamic_cast runtime check to ensure the compile-time type of the expression being cast refers to a public base class sub-object of either the cast target type (for down-cast) or most-derived object type (for cross-cast).

In previous Visual C++ releases, these dynamic casts succeeded.

// dynamic_cast_breaking_change_2.cpp
#include "stdio.h"

struct A { 
   virtual void Test() {}
};

struct B : virtual private A {
   virtual void Test() {}
};

struct D : virtual private A {
   virtual void Test() {}
};

struct C : public B, public D {
   virtual void Test() {}
};

int main() {
   C c;
   printf("%p\n", dynamic_cast<B*>((A*)&c) );
   printf("%p\n", dynamic_cast<C*>((A*)&c) );
}

Sample Output

00000000
00000000

Example

This sample shows that if any sub-objects from the source to the target of the cast are not public, the dynamic_cast cast will fail.

// dynamic_cast_breaking_change_3.cpp
#include "stdio.h"
struct A { 
   virtual void Test() {}
};

struct B : virtual public A {
   virtual void Test() {}
};

struct C : virtual private B {
   virtual void Test() {}
};

int main() {
   C c;
   printf("%p\n", dynamic_cast<B*>((A*)&c) );
   printf("%p\n", dynamic_cast<C*>((A*)&c) );
}

Sample Output

0012FF70
00000000

See Also

Reference

dynamic_cast Operator