我尝试使用Gameobject和Components制作游戏引擎,类似于Unity。我有一个组件类:
class Component
{
public:
virtual void DoTheThing(){//Doing the thing};
}
从Component派生的Texture Class,具有重写函数:
class Texture : public Component
{
public:
void DoTheThing(){//Doing a different thing};
}
带有组件映射的GameObject类,用于存储派生组件:
class GameObject
{
private:
map<string, Component> components;
Texture texture;
components["id"] = texture;
public:
Component getComponent(string id){ return components[id];}
}
最后:
int main(int argc, char* args[])
{
GameObject gameObject;
gameObject.getComponent("id").DoTheThing();
}
我想要的是能够调用派生类中存在的DoTheThing(),但它只调用基类中的DoTheThing()。
答案 0 :(得分:0)
问题出在您的GameObject
课程中
让我把它减少到相关部分:
class GameObject {
private:
map<string, Component> components;
// ...
public:
Component getComponent(string id){ /* do something and return a component */ }
};
这里你实际上正在切割你的对象 这就是调用基类方法的原因。
如果您不知道切片是什么以及如何避免切片,我建议您不要写一些类似于Unity 的内容。
我建议您阅读this Q/A了解更多详情。
答案 1 :(得分:0)
您的容器被指定为包含Component
个对象,所以当您这样做时
components["id"] = texture;
实际上,您在地图中放置了一个Component
对象,并在对象texture
上调用了复制构造函数。
为了确保多态性,容器必须包含指针,而不是预定义的类。
class Component
{ public: virtual void DoTheThing() {cout << "Component\n";} };
class Texture : public Component
{ public: void DoTheThing() override { cout << "Texture\n"; } };
class GameObject
{ map<string, Component*> components; Texture texture;
public:
GameObject() { components["id"] = &texture; }
Component& getComponent(string id) { return *components[id]; }
// Remember to return a Component& (or Component*) here, not a
// Component (by value) because otherwise you would end up with a
// base-class Component object copied from the initial Texture
// object saved in the map.
};
int main(void)
{ GameObject gameObject;
gameObject.getComponent("id").DoTheThing();
return 0;
}
<强>输出:强> 质地