如何访问基类向量中的子类变量? (对于实体组件系统)
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();
}
}
所以我有一个 "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();
}
}