2014-10-06 4 views
0

О данном случае: Проблема такая: для того, чтобы сделать мою программу кросс-платформенной, я выполнил уровень абстракции для операций, выполняемых операционной системой. Существует абстрактный базовый класс, называемый SystemComponent, который выглядит примерно так:Как сделать абстрактный класс в объект Singleton?

class SystemComponent{ 
public: 
    //some functions related to operations for OS 
    virtual WindowHandle CreateNewWindow(/*...*/) = 0; 
    virtual void Show_Message(/*...*/)   = 0; 
    //... 
} 

Это затем унаследованного другой ОС определенного класса, скажем, для Windows, его WindowsSystemComponent:

#ifdef _WIN23 

class WindowsSystemComponent : SystemComponent{ 
public: 
    virtual WindowHandle CreateNewWindow(/*...*/); 
    virtual void Show_Message(/*...*/); 
    //... 
protected: 
    //Windows specific things... 
} 

#endif 

Это WindowsSystemComponent затем impliments Отдельные функции ОС.

Чтобы создать компонент системы в Windows, я делаю это:

WindowsSytemComponent* pWSystemComp = new WindowSystemComponent(); 
//... 
//And the pass a pointer to this to the crossplatform code like this 
pFrameWork->SetSystem((SystemComponent*)pWSystemComp); 

где структура делает вызовы к функциям операционной системы, указанных в SystemComponent и передает указатель какого суб-классы нуждается.

Что нужно: Я хотел бы, чтобы удалить прохождение указателей, и сделать SystemComponent класс и специфические функции операционной системы implimentations acsessible каждому объекту, который хочет использовать их. Лучший способ сделать это, чтобы сделать его Singleton, но ИСВНА я пытаюсь сделать что-то вроде

virtual static SystemComponent* Instance() { /*...*/ }; 

внутри SystemComponent класса, который является абстрактным, я получаю ошибку компилятора, говоря такую ​​вещь не допускается.

Как же тогда я должен идти?

+1

Связанные: http://stackoverflow.com/questions/22998019/template-singleton-base-class-in-shared-object/22998472#22998472 –

ответ

4

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

+0

Но что, если существование 'WindowsSystemComponent' не известный классу SystemComponent? –

+1

@ TheLightSpark - заголовочный файл не должен знать о компонентах, специфичных для платформы, только реализация. У вас могут быть разные реализации в исходных файлах, специфичных для платформы (это то, что я думаю, что вы делаете при создании экземпляра сейчас, за исключением того, что у вас есть код инициализации платформы для конкретной платформы) – antlersoft

1

Это не может быть сделано так, как вы предлагаете. Но то, что, я думаю, могло бы решить вашу проблему, было бы использование шаблона фабрики. Wikipedia

Вы могли бы сделать что-то вроде этого:

class SystemComponentFactory 
{ 
    static SystemComponent* ptr = 0; 

    static SystemComponent getSystemComponent() 
    { 
    if (ptr == 0) 
    { 
     if (isWindows()) 
      ptr = new WindowsSytemComponent(); 
     else if (isLinux()) 
      ptr = new XwindowsSystemComponent(); 
     ... 
    } 
    return ptr; 
    } 
}; 
1

Вы не сможете создать экземпляр класса, который является абстрактным. Шаблон singleton ограничивает экземпляр класса одним объектом. Это противоречит предыдущему ограничению. Вы могли бы лучше подумать об использовании abstract factory pattern

3

Другой способ справиться с этим заключается в том, чтобы эмулировать понятие одноэлементного, но пусть производный класс задает один синглтон, который будет использоваться.

class SystemComponent 
{ 
    public: 
    static SystemComponent* instance() 
    { 
     return theInstance_; 
    } 

    //some functions related to operations for OS 
    virtual WindowHandle CreateNewWindow(/*...*/) = 0; 
    virtual void Show_Message(/*...*/)   = 0; 
    //... 

    protected: 

    static setInstance(SystemComponent* in) 
    { 
     theInstance = in; 
    } 
} 

// Define the static member. 
SystemComponent* SystemComponent::theInstance = nullptr; 

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

SystemComponent::setInstance(WindowsSytemComponent::instance()); 

При использовании другой платформы делайте аналогичную вещь.

SystemComponent::setInstance(AnotherPlatformSytemComponent::instance()); 
Смежные вопросы