2017-09-15 72 views
0

讓我們假設我有兩個具有相同的接口確定性在C++中,對象類型

class FirstChild : class Father 
{ 
    //some fields and methods useful for class A 
} 

class SecondChild : class Father 
{ 
    //some fields and methods useful for class B 
} 

後來,在代碼類似的東西做

Father* myInstance = new SecondChild(); 

現在,如果兩個類映射兩個對象我想知道對象的type,如果實例是FirstChild或SecondChild,則必須執行一些操作。我正在做類似的事情:

if (typeid (myInstance) == typeid (FirstChild)) 
{ 
    // do stuff 
} else if (typeid (myInstance) == typeid (SecondChild)) 
     { 
      // do other stuff 
     } 

這是正確的方式嗎? 因爲某處StackOverflow,我讀了typeid是不是安全,它是更方便地添加一個虛擬功能,比方說getType例如,做,在則firstChild

char* getType { return "FirstChild"; } 

說實話,我不喜歡這樣的解決方案太多了,因爲我們似乎忽略了面向對象編程中多態的強大功能。

所以,你們,你覺得呢?在C++中檢查子對象類型的最佳方法是什麼?

+0

'dynamic_cast'也許?無論如何,這樣做的需要表明你有嚴重的設計缺陷。 – user0042

+5

如果你需要知道這種類型,你可能做錯了。 – juanchopanza

+1

這聽起來像是你應該用多態和虛函數解決的問題。也許'dynamic_cast'。 – NathanOliver

回答

0

一個簡單的方法可以使用dynamic_cast。例如:

Father *myInstance = new SecondChild(); 
SecondChild *casted = dynamic_cast<SecondChild*>(myInstance); 
if (casted != nullptr) 
    std::cout << "myInstance is a SecondChild!"; 
else 
    std::cout << "myInstance is not a SecondChild!"; 

來自:cppreference: dynamic cast

如果轉換成功,dynamic_cast的返回類型NEW_TYPE的值。如果轉換失敗並且new_type是一個指針類型,它將返回該類型的空指針。如果轉換失敗並且new_type是引用類型,則會拋出一個與std :: bad_cast類型的處理程序匹配的異常。

正如@Rob指出的那樣,您可以使用虛擬函數並讓對象自己執行操作。

struct Father 
{ 
    virtual void process() = 0; 
}; 

您可以使用虛函數來決定是否應該完成操作,而不是檢查類型。

struct Father 
{ 
    virtual bool shouldProcess() { return false; } 
}; 
struct SecondChild : Father 
{ 
    bool shouldProcess() override { return true; } 
} 
1

有幾種方法可以做到這一點。

typeiddynamic_cast<>是做這件事的「官方方式」。

FirstChild *fptr = dynamic_cast<FirstChild>(myInstance); 
if (fptr) { 
    // do something 
} else { 
    SecondChild *cptr = dynamic_cast<SecondChild>(myInstance); 
    if(cptr) { 
    // do something else, and so on... 
    } 
} 

但是,這不是最優雅的方式來做到這一點。

另一種等效的方法是有一個「ID類型」,像枚舉或類似。

但正如很多人所說,如果你需要知道什麼類型,你可能會做錯誤的方式。

一個明顯的選擇是讓對象執行特定的操作。假設您在activate()函數中使用此代碼。爲什麼不使用虛擬doAction()

class Father { 
    public: 
     virtual void doAction() = 0; 
} 

//... 
myInstance->doAction(); 

有這種變化,使用不同的設計模式。但我想你明白了。