dynamic_cast 中的重大更改

更新:2007 年 11 月

在 Microsoft Visual C++ 2005 以及 Visual C++ .NET 2002 中,dynamic_cast 运算符发生了更改,这样,应用程序的行为将可能发生更改。

  • 当标准需要编译时检查时,Visual C++ 6.0 编译器允许进行运行时检查。这在 Visual C++ .NET 2002 (Visual C++ 7.0) 中已得到修复。

  • C 运行时库现在执行 dynamic_cast 运行时检查,以确保强制转换的表达式的编译时类型引用强制转换目标类型(用于向下强制转换)或派生程度最高的对象类型(用于交叉强制转换)的公共基类子对象。

有关编译器更改的更多信息,请参见 Visual C++ 编译器中的重大更改

示例

Description

在此代码示例中,变量 pA2 在 VC6 中为 NULL;编译器不执行在 ISO C++ 标准的 5.2.7/3 中指定的标识检查。但是,此强制转换将在 Visual C++ .NET 2002 (Visual C++ 7.0) 中成功开始。

因此,尽管这会导致在 Visual C++ 6.0 中引发异常,但现在却不会引发异常。

代码

// 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));
}

示例

说明

此示例显示:C 运行时库现在执行 dynamic_cast 运行时检查,以确保强制转换的表达式的编译时类型引用强制转换目标类型(用于向下强制转换)或首选派生程度最高的对象类型(用于交叉强制转换)的公共基类子对象。

在以前的 Visual C++ 版本中,这些动态强制转换可成功执行。

代码

// 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) );
}

示例输出

00000000
00000000

示例

说明

此示例显示,如果强制转换的源到目标中的任何子对象不是公共对象,dynamic_cast 强制转换将失败。

代码

// 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) );
}

示例输出

0012FF70
00000000

请参见

参考

dynamic_cast Operator