[英]Is there a way to copy a vector of derived class pointers without casting it to the base class?
[英]Is there a "cleaner" way to find the first instance of a derived class in a vector of pointers to base?
在我的游戲引擎中,我目前正在嘗試簡化代碼:
std::vector<Base*> bases; //An arbitrary vector of the abstract class Base.
/*
GetFromBase
param derivedType: An integer used for quick comparison between each derived.
return: A pointer to the first derived found, or nullptr if not found.
*/
template <typename T>
T* GetFromBase(int derivedType)
{
//Walk through each base
for (Base* b : bases)
{
//Check if its internal type is the same as the enum
if(b->GetDerivedType() == derivedType)
{
//Return the casted pointer
return reinterpret_cast<T*>(b);
}
}
//No derived of the desired type was found.
return nullptr;
}
是否可以僅使用模板參數來執行相同的功能,如果可以,是否會對性能造成很大影響?
當使用返回的指針時,您的方法具有未定義的行為,因為reinterpret_cast
通常無法在繼承層次結構中轉換指針。 僅當派生對象與基類對象指針可互轉換時,它才會做正確的事情。 這尤其是標准布局類的情況,並且具有虛函數的類從來都不是標准布局。 reinterpret_cast
不會改變指針的地址,它只是重新解釋它。
你大概意思是使用static_cast
,這並投在類層次結構,通過調整指針的必要,假設指向的對象實際上是派生類型(你與測試驗證)。
或者,您可以使用dynamic_cast
獲得相同的效果,與static_cast
相比,它本身驗證派生類型,如果對象不是派生類型,則返回空指針:
auto d = dynamic_cast<T*>(b);
if(d)
return d;
與您顯示的方法相反, dynamic_cast
不要求最衍生的類型等於T
,只是在最衍生的對象的繼承層次結構中有一個 (unique, public
) T
。
一般來說,你應該避免這樣的結構。 需要知道對象的派生類型通常表明您沒有正確設計虛擬接口。 所有基類指針的用戶應該只調用這個接口中的函數,而不關心派生類型。
另一種方法是使用dynamic_cast
template <typename T>
T* GetFromBase(std::vector<Base *> &bases)
{
for (auto b : bases)
{
// try to cast
if(auto ptr = dynamic_cast<T *>(b); ptr) // <- c++17 syntax
{
return ptr;
}
}
return nullptr;
}
還有使用std::find_if 的較短版本
template <typename T>
T* GetFromBase(std::vector<Base *> &bases)
{
auto it = std::find_if(begin(bases), end(bases), [](Base *b) {
return dynamic_cast<T *>(b);
});
return it == end(bases) ? nullptr : dynamic_cast<T *>(it);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.