共用方式為


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 執行階段檢查,以確保編譯時期所轉換的運算式型別會參考到轉換目標型別 (針對向下轉換而言) 或最末層衍生的物件型別 (針對交叉轉換而言) 的公用基底類別 (Base Class) 子物件。

如需編譯器變更的詳細資訊,請參閱 Visual C++ 編譯器的重大變更

範例

描述

在此程式碼範例中,VC6 的 pA2 變數為 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 執行階段檢查,以確保編譯時期所轉換的運算式型別會參考到轉換目標型別 (針對向下轉換而言) 或最末層衍生的物件型別 (針對交叉轉換而言) 的公用基底類別 (Base Class) 子物件。

在之前的 Visual C++ 發行版本中,這些動態轉換 (Dynamic Cast) 都會成功。

錯誤碼

// 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