2012-04-05 5 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(); 
} 

Второй Синглтона (FontManager) - это точно то же самое, но вместо указателя FontManager есть указатель TextureManager, а в его конструкторе он инициализирует этот указатель с помощью TextureManager :: Instance(). Это должно работать следующим образом: TextureManager запускается сначала (при запуске программы), и в его конструкторе впервые запускается однострочный шрифт FontManager, вызывающий FontManager :: Instance(). FontManager, в своем конструкторе, назначает свой указатель TextureManager с TextureManager :: Instance(), и этот метод возвращает экземпляр TextureManager, который уже существует. Правильно?

Но вместо этого программа вводит бесконечный цикл, потому что (я не знаю почему) методы Instance() всегда создают новый экземпляр. Мне нравится, что if (instance==0) всегда оценивается как true.

+0

Зачем вам этот шрифтManager? это также Singleton ... так что вы можете использовать его позже ... не в конструкторе textureManager – fen

ответ

7

Поскольку вы написали бесконечный цикл, в котором конструктор TextureManager вызывает конструктор FontManager, который затем вызывает конструктор TextureManager .... и так далее.

Поскольку конструктор должен быть выполнен до назначения статических переменных, вы попадете в этот цикл.

+0

Большое вам спасибо, я сделал действительно глупую ошибку. Я возьму назначение указателей из конструкторов. Я приму ответ, как только смогу – XaitormanX

+0

@ XaitormanX Порядок ошибок инициализации с 'Singleton's. Ба! Просто сделайте это и передайте его. Вам не нужно, чтобы он был глобальным, и только один экземпляр. Это просто удобство, а это значит, что вы не задумываетесь о своем дизайне (в данном случае порядке инициализации). –

0

Для синглтонов вы не открываете конструктор в качестве открытого интерфейса. Вместо этого, у вас есть отдельный, статический экземпляр-поисковая функция-члена и частный конструктор:

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

В качестве альтернативы статического члена вы также можете сделать свой указатель трюк, но тогда вы должны иметь static std::unique_ptr<Foo>, чтобы обеспечить надлежащее уничтожение в конец программы.

Смежные вопросы