2013-01-10 112 views
4
template <class T> void checkObject(T genericObject) 
    { 
     MyClassA* a = dynamic_cast<MyClassA*>(genericObject); 
     if (a != NULL) 
     { 
     //we know it is of type MyClassA 
     } 
     MyClassB* b = dynamic_cast<MyClassB*>(genericObject); 
     if (b != NULL) 
     { 
     //we know it is of type MyClassB 
     } 
    } 

是這樣的可能嗎?我們有一個模板類型,但我們想知道它是實際類型?是否可以使用dynamic_cast進行模板類型檢查?

+1

是的,它可能,但它肯定會是一個糟糕的設計選擇。你究竟在做什麼? –

+1

您也可以重載該函數並獲得編譯時檢查。 –

+0

@ K-ballo:只有這些類具有虛擬功能纔可能不是嗎?否則不是UB? –

回答

7

在你可能只想專注模板,每個類型的,而不是做一個運行時檢查模板的世界,即

template<typename T> 
void foo(T obj); 

template<> 
void foo<MyClassA>(MyClassA obj) { 
} 

template<> 
void foo<MyClassB>(MyClassB obj2) { 
} 

這將允許編譯器生成在編譯時正確的模板根據你的參數推斷。

基於一個實例的靜態類型這個只解決,就是沒有你的變量是一個MyClassCMyClassB繼承,因此應使用通用的形式,編譯時的知識。所以這是行不通的:

MyClassC* cinstance = new MyClassC(); 
    foo(cinstance); //compiler error, no specialization for MyClassC 

一般來說,這指向一個編譯時和運行時多態性是非常不同的系統一般規則。在沒有繼承知識的情況下,模板嚴格處理靜態類型的領域。這可能會讓來自Java/C#的人們感到驚訝,這兩個特性之間的融合更加無縫。

對於一類的功能運行時的專業化,你的選擇是

  1. 定義虛擬方法 - 如果這種功能位真正的應該是該對象的一部分,可能不適合取決於
  2. 使用dynamic_cast(你現在正在做的) - 有點皺眉,但可以成爲每個人都能得到的最直接的解決方案。
  3. Visitor Pattern - 一種使用重載在運行時解析爲正確類型的函數的設計模式。
+3

只有在使用顯式模板參數調用時纔會調用專用版本的「foo」。此外,它只適用於「MyClassA」,而不適用於MyClassA。 –

+0

+1 definetely更好的解決方案 –

+1

@ K-ballo,正常的函數重載將處理。對於這種簡單的情況,不需要模板。 – Tomek

1

是的,這是可能的。請注意,動態轉換髮生在運行時和模板生成代碼durign編譯。因此該函數仍然會生成,但會在運行時檢查您描述的情況。

編輯:看看道格T.的答案正確的方式來做你想做的事情。

4

這是可能的,但MyClassAMyClassB必須至少有一個虛成員函數爲了dynamic_cast工作。我也相信你實際上想在你的函數的簽名中有(T* genericObject)而不是T genericObject(否則就沒什麼意義了)。基於模板特

解決方案是靜態多態性 OK,但我相信這個問題是如何使運行時輸入的類型檢測。我想象用一個類型爲MyClassA超類MyClassB的超類類型的指針調用模板。 在這種情況下,模板專業化將失敗以提供正確的答案。

無論如何,我有一種強烈的感覺,你正在試圖做錯事來達到你想達到的目的(不管它是什麼)。當你發佈這樣的問題時,我建議你明確你想去哪裏,你的目標是;這可能僅僅是沿着錯誤路徑的障礙

相關問題