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