2013-08-19 80 views
1

所以我有一個類層次結構,其基本上具有Entity類作爲父抽象類和一束從它派生的其他類的的STL矢量調用一個特定對象的功能,如DoorPlayerGround上多態對象

我也有一個三維vector存儲指針Entity類型的對象,我用這個派生對象填充這個vector。 在Door類中,我有一個名爲isOpen()的方法,它簡單地返回bool。此函數特定於Door類,並且在Entity類中以及它的任何其他派生類型中均未找到(因爲我不需要檢查例如Ground對象是否打開)。現在

,知道有在vectori位置,jkDoor存在類型的對象,我想調用的方法isOpen像這樣:vector[i][j][k]->isOpen()。不幸的是,當我這樣做時,編譯器返回class Entity has no member named isOpen()。這是可以理解的,因爲函數isOpen()Door類是排他性的,但是爲了使這種調用成爲可能,我可以做些什麼?

+1

不要只告訴我們你的代碼; ***顯示***它*更*更有效率。其次,['dynamic_cast <>'](http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-and-reinterpret-cast-be-used)可能有些用處您。不要只是把它扔進去,閱讀如何使用它**先**。 – WhozCraig

回答

2

解決此問題的一種方法是首先將其投射到Door *。但是,爲了減少這種類型的安全性,您應該使用dynamic_cast<Door *>()。如果Entity尚不具有虛擬方法,則可以添加虛擬析構函數。

class Entity { 
    //... 
    virtual ~Entity() {} 
}; 

void foo (Entity *e) { 
    //... 
    Door *door = dynamic_cast<Door *>(e); 
    if (door) { 
     if (door->isOpen()) { 
      //... 
     } 
    } 
    //... 
} 
2

簡短的回答:

演員實體下降到門:static_cast<Door*>(vector[i][j][k])->isOpen()

龍答:

你的設計是不妥當的,如果你需要知道具體的派生類型是在特定的位置。解決這個問題可能很簡單,只需將isOpen()函數移動到實體,並返回true即可。或者它可能需要重新考慮與vector成員一起使用的代碼。

+4

如果被指向的實體* *實際上是一個'Door'或者一個派生的'Door'進一步下層,這是**未定義的行爲**,並且最肯定會崩潰。 'static_cast <>'不是*這裏使用的類型。看到它的描述[在這個問題和答案](http:// stackoverflow。com/questions/332030/when-should-static-cast-dynamic-cast-and-reinterpret-cast-be-used)爲什麼。 – WhozCraig

+0

你會想使用'reinterpret_cast',而不是'static_cast' - 儘管這種方法不是推薦的方法。長遠的答案更符合實際 - 修復設計。 –

+0

啊,謝謝你建議使用類型轉換。 在班級重新設計方面,你有什麼建議,我會怎麼做呢?看起來,與同一個父類的多個對象的向量是我的程序不可或缺的:( – Nonomus

2

考慮多態鑄造用dynamic_cast<>對於引用如果目標類型是不兼容的,將簡單的返回NULL會拋出異常(std::bad_cast),但指針的語言支持,所以......假設你的基類和它的派生確實是多態的(即至少一個虛擬方法):

Door* pDoor = dynamic_cast<Door*>(vector[i][j][k]); 
if (pDoor) 
    pDoor->isOpen(); 

有關設計的評論版主。意見就像...是的。每個人都有一個。