2012-04-05 47 views
0

我有兩個單身,第一個的頭看起來像這樣(我省略了不相關的Singleton模式的所有內容):這個單身模式爲什麼不起作用?

#ifndef TEXTUREMANAGER_DEFINED_H 
#define TEXTUREMANAGER_DEFINED_H 
class FontManager; 
class TextureManager 
{ 
private: 
    static TextureManager *instance; 
    TextureManager(); 
public: 
    FontManager *fontManager; 
    static TextureManager* Instance(); 
}; 

#endif 

並在實施,這是Instance()方法(和實例靜態成員的初始化):

#include "FontManager.h" 
TextureManager * TextureManager::instance = 0; 
TextureManager* TextureManager::Instance() 
{ 
    if (instance==0) 
     instance=new TextureManager; 
    return instance; 
} 

這是構造函數:

TextureManager::TextureManager() 
{ 
    fontManager=FontManager::Instance(); 
} 

第二單的(FontM anager)的設計完全一樣,但是不是FontManager指針具有TextureManager指針,而是在其構造函數中使用TextureManager :: Instance()初始化該指針。 這應該像這樣工作:TextureManager首先實例化(當程序啓動時),並且在它的構造函數實例中第一次調用FontManager單例調用FontManager :: Instance()。在它的構造函數中,FontManager使用TextureManager :: Instance()將其指針指定給TextureManager,並且此方法返回已存在的TextureManager實例。對?

但是,而不是程序進入無限循環,因爲(我不知道爲什麼)Instance()方法總是創建一個新的實例。我喜歡if (instance==0)總是評估爲真。

+0

你爲什麼需要這個fontManager?它也是單例...所以你可以稍後使用它...不在紋理管理器的構造函數中 – fen 2012-04-05 09:15:22

回答

7

因爲你寫了一個無限循環,其中TextureManager的構造函數調用的FontManager構造函數,然後調用的TextureManager構造....等等。

因爲構造函數必須在分配靜態變量之前完成,所以最終會在此循環中完成。

+0

非常感謝你,我犯了一個非常愚蠢的錯誤。我將從構造函數中取出指針賦值。我會盡快接受答案 – XaitormanX 2012-04-05 09:18:37

+0

@XaitormanX使用'Singleton's初始化錯誤的順序。呸!只需製作一個並傳遞給它。你不需要它是一個只有一個實例的全局。這只是一種便利,這意味着你不會仔細考慮你的設計(在這種情況下,初始化的順序)。 – 2012-04-05 10:22:06

0

對於單例,您不要將構造函數作爲公共接口公開。取而代之的是,你有一個單獨的靜態實例檢索成員函數和一個私人的構造函數:

class Foo 
{ 
    Foo() { /* ... */ } 
public: 
    static Foo & get() 
    { 
     static Foo instance; // uses private constructor 
     return instance; 
    } 
}; 

或者到靜態成員,你還可以做你的指針伎倆,但你應該有一個static std::unique_ptr<Foo>以確保適當的銷燬,該計劃結束。