如何访问基类向量中的子类变量? (对于实体组件系统)

How do I access subclass variables in a baseclass vector? (for an entity component system)

所以我有一个 "Components" 的向量。我可以轻松地从向量访问组件变量,但是当我向向量添加子类时,我无法访问这些变量。

也许这是一个非常大胆的问题,解决方案可能非常复杂,但我不知道从哪里开始,也不知道该尝试什么,所以感谢您的帮助。

struct Component {};
std::vector<Component> components;

struct Transform : Component
{
    int x, y;
};

void Start()
{
    components.push_back(Transform());
    //can't acces x below
    std::cout << components[0].x;
}

解决方案

为唯一指针创建向量:

std::vector<std::unique_ptr<Component>> components;

第 2 步:

void Start()
{   
    //add component (pointer to vector)
    components.push_back(std::make_unique<Transform>());
    //cast to Transform
    Transform const* transform = static_cast<Transform*>(components[0].get());

    std::cout << transform->x;
}

问题是,您的向量存储 class Component 的对象。 push_back 中发生的事情是,向量创建了一个新的 Component,它是从您的 Transform() 对象 复制的

所以这里要注意的第一件大事是,您并没有真正将 Transform 对象推入向量,因此不存在 .x.

请注意,在 C++ 中,仅行 Transform x{}; 在堆栈上创建一个对象。因此 Component y=x; 创建另一个对象并从 x.
复制它的数据(在本例中是 none,因为 Component 是空的) 这基本上就是您的代码中发生的事情,只是在向量中隐藏了一点。

首先你有对象切片的问题,要排序你可以做这样的事情:

struct Component {};
std::vector<std::unique_ptr<Component>> components;

struct Transform : Component
{
   int x = 0, y = 0;
};

void Start()
{
    components.push_back(std::make_unique<Transform>());
}

至于访问 Transform 的成员,您有两种选择。 C++ 已内置 rtti 但请注意它非常慢:

Transform const* transform = dynamic_cast<Transform*>(components[0].get());
if(transform != nullptr)
    std::cout << transform.x;

另一种选择是从 Component 实现虚函数:

struct Component
{
    virtual void Update();
};

struct Transform : public Component
{
    int x = 0, y = 0;
    virtual void Update() override
    {
        std::cout << x;
    }
};

void Start()
{
    components.push_back(std::make_unique<Transform>());
    for(Component& component : components)
    {
        component.Update();
    }
}