组件系统上铸反向

Reversal of Upcasting for Component system

本文关键字:系统 组件      更新时间:2023-10-16

我目前正在开发一个用c++编写的基于组件的游戏引擎。所有组件都继承自组件基类。场景中的所有组件都被上传到组件的向量中,如果它们可以被迭代,则可以调用Update()

我正在尝试为这些组件设计一个通信系统。如果我有一个名为GetComponent<Type>()的函数,就像Unity一样,我将能够从上传之前的状态返回一个组件。

所以基本上我有一个upcasted组件,我想反转它,使它成为它的原始类,然后通过函数返回它(就像它以前的类一样)。这可能吗?如果可能的话,组件如何知道它曾经是什么类?

有什么这样的例子我可以借鉴吗?

我假设向上转换组件意味着将指向它的指针(或引用)转换为指向基类的指针。在这种情况下,请使用dynamic_cast<Derived *>(pointer)(或dynamic_cast<Derived &>(reference))在运行时进行安全的下转换。

要实现这一点,您必须在将组件添加到集合(向上转换)之前了解组件的原始类型。

因此,知道了这一点,就可以这样做(假设componentComponent*类型):

SpecificComponent* specific = dynamic_cast<SpecificComponent*>(component);

并不是说dynamic_cast会失败=>如果实际的组件类型不适用,上面可以将specific设置为nullptr。这一点,以及它比其他类型转换慢的事实,使它成为C++类型转换中最不受欢迎的。

您还可以查看boost::polymorphic_download,它的功能类似。如果在DEBUG模式下失败,它会生成dynamic_cast并断言,但在RELEASE模式下会执行更快的static_cast

如果您有RTTI,那么可以很容易地进行映射。我建议有两个功能CCD_ 11&GetComponentDerived

template< typename Type >
Type* GameObject::FindComponentExact( size_t a_Index )
{
    size_t found = 0;
    for( ComponentVector::iterator itrCur = m_Components.begin(), itrEnd = m_Components.end(); itrCur != itrEnd; ++itrCur )
        if( typeid( Type ) == typeid( *(*itrCur) ) && found++ == a_Index )
            return static_cast< Type* >( *itrCur );
    return NULL;
}
template< typename Type >
Type* GameObject::FindComponentDerived( size_t a_Index )
{
    size_t found = 0;
    for( ComponentVector::iterator itrCur = m_Components.begin(), itrEnd = m_Components.end(); itrCur != itrEnd; ++itrCur )
        if( dynamic_cast< Type* >( *itrCur ) && found++ == a_Index )
            return static_cast< Type* >( *itrCur );
    return NULL;
}

这就是它在我的引擎中的样子,我有一个默认为0的索引,让我可以迭代所有实例,因为我可以拥有特定组件的多个实例。