2013-12-13 65 views
1

我想添加我的對象指針到矢量相同的時間對象被創建。目前我已經在對象的構造函數中完成了它,但是現在我已經聽說這是一種錯誤的方法,因爲在那個點上對象不是完全創建的。如何在C++中創建對象時將對象指針推向矢量?

的MyObject類的構造函數:

// MyObject constructor 
MyObject::MyObject() { 
    // add object to vector of all objects 
    MyObjectManager::Instance()->objects.push_back(this); 
} 

myObject的是隻爲對象的基類。我也有從MyObject繼承的MyRectangle類,所以當我創建新的MyRectangle時,然後調用MyObject構造函數,並將我新創建的對象推入到MyObjectManager的向量中。

MyObjectManager是一個單例類,它保存所有對象的列表並非常頻繁地調用它們的虛擬繪製函數。這是問題嗎? MyObjectManager可能會在完全創建對象之前調用對象的Draw函數?

我可以做一個單獨的方法來添加對象向量。事情是這樣的:

MyObject::Create() { 
    // add object to vector of all objects 
    MyObjectManager::Instance()->objects.push_back(this); 
} 

但後來我不得不用這樣的:

MyRectangle *rect = new MyRectangle(0.5, 0.5, 0.1, 0.1); 
rect->Create(); 

我只是希望能夠簡單地通過構造這樣的實例化新的對象:

MyRectangle *rect = new MyRectangle(0.5, 0.5, 0.1, 0.1); 
+0

_'calls他們的虛擬繪圖功能非常頻繁。這是問題嗎?'_很可能! –

+0

你可以看看這個答案的有關在構造函數內調用虛函數的問題http://stackoverflow.com/a/3905886/356440 –

回答

2

你可以在你的構造函數中做到這一點,不是嗎?

MyRectangle::MyRectangle(const float& a, const float& b, const float& c, const float& d) { 
    this->Create(); 
} 
+0

這是行不通的嗎?如果我在contsructor裏面調用Create函數,那麼是不是和只是在構造函數中推向矢量一樣? – user19985

+0

@ user19985不,它不一樣。如果您在MyRectangle構造函數中調用Create,則MyObject構造函數已經完成,那就沒問題。正如我在評論中告訴你的那樣,你可以看看這個問題的答案stackoverflow.com/a/3905886/356440。 –

+0

@StephaneRolland好的,謝謝。我實際上讀了這個答案,但顯然不明白一切:) – user19985

0

如果您可以保證在完全構建之前不會訪問對象,而只是存儲對象,則不會像使用指針那樣使用指針。如果有另一個線程處理繪製更新,例如,輪詢管理器類中的所有對象並定期調用它們的draw函數,則保證被破壞。

看看this問題和this一個更多的信息。

1

也許你可以考慮使用工廠模式:

MyRectangle * factoryMyRectangle(float x, float y, float w, float h) 
{ 
    MyRectangle *rect = new MyRectangle(x,y,w,h); 
    rect->Create(); 
    return rect; 
} 

,你可以撥打:

MyRectangle *rect = factoryMyRectangle(0.5, 0.5, 0.1, 0.1); 
1

在很大程度上取決於上下文。如果push_back是構造函數中的最後一個 指令,並且沒有派生的 類,則應該沒有問題。同樣,如果你在 一個單線程環境中(並且因爲你沒有做任何鎖定,所以你必須),並且派生類不會做任何事情,通過向量中的指針 ,沒有問題。只要您不嘗試使用它們指向的實際對象,就可以使用 指針指向尚未完全構建的對象,即 。

這可能是一個問題的一種情況是,如果您在多線程環境中使用基類構造函數 。如果 將指針推向不是完全構造的對象,並且 則另一個線程接管,在 向量中查找該對象,並嘗試使用它,則遇到問題。有 各種技術來處理這種情況:最常見的可能是 使用工廠功能來構建所有對象,並有 工廠功能做push_back,構造函數完成後 。所以你永遠不會打電話new MyRectangle(...) 以外的工廠功能。 (通常情況下,工廠 功能將是一個靜態成員,和構造將是 私有的,這樣可以保證這一點。)

請注意,如果你使用的工廠函數,你會probaby 要保持的new在智能指針,直到 push_back結果已完成:

std::unique_ptr<MyRectangle> tmp(new MyRectangle(...)); 
MyObjectManager::Instance()->objects.push_back(tmp.get()); 
tmp.reset() 
2

如果你有特殊MyObjectManager類,你也可以使用它作爲一個工廠對象。 要illustarate它充分考慮代碼:

struct MyObjectManager { 

    template <typename T, typename... Args> 
    T * createObject(Args... args) { 
     T *ret = new T(args...); 
     m_objects.push_back(ret); 
     return ret; 
    } 

    std::vector<MyObjects *> m_objects; 
}; 

創建對象:

MyRectangle *rect = MyObjectManager::Instance()->createObject<MyRectangle>(1.0, 2.0, 3.0, 4.0); 
+0

謝謝你的回答,這是非常有用的,但這一次我會與Velthune的答案一起去。 – user19985