2014-10-10 67 views
1

因此,我正在研究各種各樣的遊戲引擎,並且我一直在爲這個問題奮鬥了一段時間。我不確定它是否是設計問題,或者我只是沒有必要的瞭解C++從指針向量到基類型,返回派生類型的第一個元素,作爲派生類型轉換

簡而言之,我有一個指向「BaseComponent」類型的指針向量。它由指向派生類,AComponent,BComponent等的指針組成。我想知道是否有一種優雅的方式來返回給定派生類型的向量中的第一個元素,並將它轉換爲正確的派生類型。在僞代碼:

BComponent * bComp = getFirstElementOfType(vectorOfComponents, BComponent); 

而且它會自動地找到匹配放在第二個參數類型的第一個元素,如果在載體中沒有組件類型相匹配返回它澆鑄成正確的派生類型,或者爲null。我假設我們必須爲這樣的事情使用模板(如果可能的話),但是經過一段時間的修改之後,我還沒有拿出任何能夠完成這項工作的東西。希望一切都有意義,謝謝你的時間。

+1

遺憾,它沒有任何意義。返回類型應該是指針或引用 – 2014-10-10 07:20:38

+0

聽起來就像你需要一個協變類型的返回類型。參考和指針可以幫助解決這個問題。你可能也想考慮'shared_ptr'這裏 – Niall 2014-10-10 07:32:54

+1

你有幾個答案可以完成這個工作,但是,一般來說,如果你發現自己在做一些「動態演員,直到有東西粘住」,你就會遇到更深層次的問題。 RTTI和動態鑄造是昂貴的,並且你正在生產*遊戲引擎。更可能你應該在基類上有幾個虛擬方法,例如:'CanShoot()''CanMove()','IsScenery()'。 (這些似乎可能是遊戲對象的屬性。:-)) – 2014-10-10 08:53:31

回答

2

你可以這樣做:

template <typename Derived> 
Derived* getFirstElementOfType(const std::vector<BaseComponent*>& components) 
{ 
    for (auto* component : components) { 
     auto* p = dynamic_cast<Derived*>(component); 
     if (p != nullptr) { 
      return p; 
     } 
    } 
    return nullptr; 
} 

template <typename Derived> 
Derived* getFirstElementOfType(const std::vector<BaseComponent*>& components) 
{ 
    auto it = std::find_if(components.begin(), components.end(), 
     [](BaseComponent* component) 
     { 
      return dynamic_cast<Derived*>(component) != nullptr; 
     }); 
    if (it != components.end()) { 
     return static_cast<Derived*>(*it); 
    } 
    return nullptr; 
} 

,並呼籲它這樣:

BComponent* bComp = getFirstElementOfType<BComponent>(vectorOfComponents); 
+0

我只是試過這個,它似乎是完美的工作,謝謝! – 2014-10-10 07:43:32

+0

雖然很好,但它可以簡化爲一個'find_if' +通用lambda(C++ 14)。 – edmz 2014-10-10 07:55:49

+0

@black:我普遍同意,但是在這裏我發現代碼不太清晰(無論如何都添加了代碼)。 – Jarod42 2014-10-10 08:01:08

1

我會定義類似std::exception類的成員函數的函數

virtual const char* what() const noexcept; 

並用它來查找目標派生類的指針。

1

像這樣的事情,以便返回特定類型:

template<typename TBase, typename UDerived> 
UDerived* findFirstOfType(std::vector<TBase*> & items) 
{ 
    for (auto item : items) { 
     if ((auto d = dynamic_cast<UDerived*>(item)) != nullptr) 
     return d; 
    } 
    return nullptr; 
} 

調用,如:

Orange * orange = findFirstOfType<Fruit, Orange>(items); 
+0

我把它清理乾淨了。舊習難改;自2003年以來,我大部分時間都花在C#和Java(ugg)上,所以我錯過了C++ 03在if條件中添加_declaration的事實。我不敢相信我錯過了這樣一個優雅的功能!從1992年到2002年,我做了十年的C++,但在那之後,我開始使用其他語言,並且錯過了很多新功能,直到今年,當我意識到我的C++技能已經過時了很多年,並訂購了我的一些新版本舊書。我想知道我還錯過了什麼! – codenheim 2014-10-10 08:40:07