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



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

也许这是一个非常大胆的问题,解决方案可能真的很复杂,但我不知道从哪里开始以及尝试什么,所以任何帮助都值得赞赏。

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;
}

首先,您在对象切片方面遇到了问题,要排序,您可以执行以下操作:

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();
}
}

问题是,你的向量存储类Component的对象。push_back中发生的情况是,向量创建一个从Transform()对象复制的新Component

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

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

最新更新