簡體   English   中英

是否有一種“更干凈”的方法可以在指向基類的指針向量中找到派生類的第一個實例?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM