1

我正在为一个项目设计实体组件系统,而 C++ 内存管理给我带来了一些问题。我只是想确保我的设计是合法的。

所以首先我有一个实体类,它存储一个组件向量:

class Entity
{
    private: 
        std::vector<std::unique_ptr<Component> > components;
    public:
        Entity() { };
        void AddComponent(Component* component)
        {
            this -> components.push_back(std::unique_ptr<Component>(component));
        }
        ~Entity();
};

如果我没记错的话,这意味着当调用析构函数时(即使是默认的,编译器创建的),实体的析构函数将调用~components,它将为向量中的每个元素调用~std::unique_ptr,并且导致每个组件的破坏,这就是我想要的。

组件类有虚方法,但重要的是它的构造函数:

Component::Component(Entity parent)
{
    parent.addComponent(this)  // I am not sure if this would work like I expect
    // Other things here
}

只要传递this给该方法有效,这也可以满足我的要求。我的困惑是在工厂里。我想要做的是类似的事情:

std::shared_ptr<Entity> createEntity()
{
    std::shared_ptr<Entity> entityPtr(new Entity());
    new Component(*parent);
    // Initialize more, and other types of Components
    return entityPtr;
}

现在,我相信此设置会将组件的所有权留在其父实体手中,这正是我想要的。首先是一个小问题,我是否需要通过引用或指针之类的方式将实体传递给 Component 构造函数?如果我理解 C++,它将按值传递,这意味着它会被复制,并且复制的实体将在构造函数结束时消失。

第二个也是主要问题是基于此示例的代码将无法编译。完整的错误太大,无法在此处打印,但我想我知道发生了什么。编译器的错误说我不能删除不完整的类型。我的 Component 类有一个带有实现的纯虚拟析构函数:

inline Component::~Component() { };

在标题的末尾。然而,因为整点是 Component 实际上是一个接口。我从这里知道unique_ptr 销毁需要一个完整的类型。问题是,我该如何解决这个问题?作为参考,我使用的是 gcc 4.4.6。

4

1 回答 1

2
Component::Component(Entity parent)

通过 calue 获取父级,因此您将组件添加到此临时组件中,该组件将在功能结束时消失。而原版会错过这个电话。尝试

Component::Component(Entity &parent)

对于另一部分,您必须确保在模板实例化的地方类型是完整的。通常的方法是像你一样在类中声明 dtor,然后将实现放在定义所需类型的 .cpp 中。内联并不是真正必要的。或者您可以在 Entity 之前包含另一个标头,如果 in 不会导致循环包含。

于 2013-06-30T21:58:14.400 回答