2008-12-09 49 views
115

我有一個類A和從它繼承另一個類的類型,B.我重寫接受類型A的對象作爲參數的函數,因此我必須接受的A.不過,我稍後調用只有B有的函數,所以如果傳遞的對象不是B類,我想返回false而不繼續。查找C中的對象++

什麼是找出傳遞給我的函數的對象類型的最佳方法是什麼?

回答

134

的dynamic_cast應該做的伎倆

TYPE& dynamic_cast<TYPE&> (object); 
TYPE* dynamic_cast<TYPE*> (object); 

dynamic_cast關鍵詞從一個指針或引用類型到另投下了一個基準,執行運行時檢查,以確保投的有效性。

如果試圖轉換爲指針類型,它是不是一個類型的實際對象的,演員的結果將是NULL。如果您嘗試轉換爲引用不是實際對象類型的類型,則該轉換將拋出異常。

確保有在基類中的至少一個虛擬功能進行dynamic_cast的工作。

+0

你的意思是在基類中必須有一個虛函數才能使dynamic_cast工作。我認爲這很重要,我只是猜測。 – GiCo 2015-08-19 08:20:37

+0

確定發現它:運行時類型信息(RTTI)僅適用於多態的類,這意味着它們至少有一個虛擬方法。 dynamic_cast和typeid需要RTTI。 – GiCo 2015-08-19 08:54:23

+0

如果它不可轉換,不會拋出`dynamic_cast`?有沒有辦法做到這一點,而不產生投擲? – jww 2016-08-31 11:38:26

19

這就是所謂的RTTI,但你幾乎肯定要重新考慮你的設計在這裏,因爲找到的類型,做基於它特別的東西使你的代碼更脆。

+3

確實。不幸的是,我正在研究一個現有的項目,所以我無法真正改變設計,或者A類中的任何東西。 – lemnisca 2008-12-09 05:23:38

6

您是否在尋找dynamic_cast<B*>(pointer)

2

你的描述有點混亂。

一般來說,儘管一些C++實現有它的機制,但你不應該問這個類型。相反,您應該對指向A的指針執行dynamic_cast。這將會執行的是在運行時,將檢查指向A的指針的實際內容。如果你有一個B,你會得到你的指針B.否則,你會得到一個異常或null。

+1

應該注意,如果您執行的參考演員失敗,您將得到一個異常*。 即dynamic_cast (t)。 失敗的指針轉換返回NULL。 (t) – AlfaZulu 2008-12-09 05:14:21

+0

是的,我應該澄清,更好。謝謝。 我希望有一個詞的C型描述是通過引用,而不是按價值。 – Uri 2008-12-09 05:21:11

8

可能嵌入到您的對象的ID的「標籤」,並用它的類A的對象和類B.

的對象之間進行區分然而,這顯示了在設計的一個缺陷。理想情況下,A中沒有的B中的方法應該是A的一部分,但保留爲空,B將覆蓋它們。這消除了特定於類的代碼,更符合OOP的精神。

2

正如其他人表示你可以使用dynamic_cast。但是通常使用dynamic_cast來找出你正在處理的派生類的類型,這表明了糟糕的設計。如果您重寫了一個函數,該函數將A的指針作爲參數,那麼它應該能夠使用A類本身的方法/數據,並且不應該依賴於類B的數據。在您的情況下,如果您不是重寫確信你寫的方法只適用於B類,那麼你應該在B類中寫一個新方法。

0

使用重載函數。不需要的dynamic_cast甚至RTTI支持:

class A {}; 
class B : public A {}; 

class Foo { 
public: 
    void Bar(A& a) { 
     // do something 
    } 
    void Bar(B& b) { 
     Bar(static_cast<A&>(b)); 
     // do B specific stuff 
    } 
}; 
113

動態轉換是最適合你的問題, 描述,但我只想補充一點,你可以找到類的類型有:

#include <typeinfo> 

... 
string s = typeid(YourClass).name() 
2

因爲你的類不是多態的。試試:

struct BaseClas { int base; virtual ~BaseClas(){} }; 
class Derived1 : public BaseClas { int derived1; }; 

現在BaseClas是多態的。我將類更改爲struct,因爲默認情況下,結構的成員是公共的。

3

只要是完整的,我將建立蓄客Robocide的,並指出不使用名稱()的typeid可以單獨使用:

#include <typeinfo> 
#include <iostream> 

using namespace std; 

class A { 
public: 
    virtual ~A() = default; // We're not polymorphic unless we 
          // have a virtual function. 
}; 
class B : public A { } ; 
class C : public A { } ; 

int 
main(int argc, char* argv[]) 
{ 
    B b; 
    A& a = b; 

    cout << "a is B: " << boolalpha << (typeid(a) == typeid(B)) << endl; 
    cout << "a is C: " << boolalpha << (typeid(a) == typeid(C)) << endl; 
    cout << "b is B: " << boolalpha << (typeid(b) == typeid(B)) << endl; 
    cout << "b is A: " << boolalpha << (typeid(b) == typeid(A)) << endl; 
    cout << "b is C: " << boolalpha << (typeid(b) == typeid(C)) << endl; 
} 

輸出:

a is B: true 
a is C: false 
b is B: true 
b is A: false 
b is C: false 
0

如果您可以訪問增強庫,也許type_id_with_cvr()函數是你需要的,它可以是provide data type without removing const, volatile, & and && modifiers。這裏是C++ 11中的一個簡單例子:

#include <iostream> 
#include <boost/type_index.hpp> 

int a; 
int& ff() 
{ 
    return a; 
} 

int main() { 
    ff() = 10; 
    using boost::typeindex::type_id_with_cvr; 
    std::cout << type_id_with_cvr<int&>().pretty_name() << std::endl; 
    std::cout << type_id_with_cvr<decltype(ff())>().pretty_name() << std::endl; 
    std::cout << typeid(ff()).name() << std::endl; 
} 

希望這是有用的。