2013-06-30 96 views
1

我正在爲一個項目設計和實體組件系統,而C++內存管理給了​​我幾個問題。我只是想確保我的設計是合法的。Unique_ptr編譯器錯誤

所以開始我有存儲組件的載體的實體類:

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

哪,如果我沒有記錯的話意味着,當調用析構函數(即使是默認的,編譯器創建一個),該析構函數將調用〜組件,它將爲vector中的每個元素調用〜std :: unique_ptr,並導致每個Component的銷燬,這正是我想要的。

組件類有虛擬方法,但重要的部分是它的構造:

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++,它會通過值傳遞,這意味着它被複制,並且複製的實體會死在構造函數的末尾。

第二,主要問題是基於此示例的代碼不會編譯。完整的錯誤太大,無法打印,但我想我知道發生了什麼。編譯器的錯誤說我不能刪除一個不完整的類型。我的組件類有一個純粹的虛擬析構函數,執行如下:

inline Component::~Component() { }; 

在頭部的末尾。但是,由於整個觀點是Component實際上是一個接口。我從here知道unique_ptr銷燬需要一個完整的類型。問題是,我該如何解決這個問題?作爲參考,我使用的是gcc 4.4.6。

回答

2
Component::Component(Entity parent) 

父母通過calue,所以你添加組件到這個臨時的,這將消失在函數結束。原來會錯過這個電話。嘗試

Component::Component(Entity &parent) 

對於其他部分,您必須確保類型在模板實例化的地方完成。 通常的做法是像你一樣在類中聲明dtor,然後將實現放在所需類型定義的.cpp中。內聯並不是真的有必要。 或者你可以在Entity之前包含其他標題,如果不會導致循環包含。

+0

好的,那就是我的想法。謝謝。 –

+0

更改簽名不會解決OP的問題。他們將'this'的所有權傳遞給'unique_ptr'。 – jrok

+0

@jrok:請詳述一下嗎?是的,Component只是用新的方式創建的,並且隱含地將其所有權傳遞給「父」實體。哪個問題沒有解決? (我假設最後一塊意味着* entityPtr真的是參數) –