Reputation: 504
What the case is about:
The problem stands like this- In order to make my program cross-platform, I have done an abstraction layer for the operations performed by the operating system. There is an abstract base class, called SystemComponent
which looks something like this:
class SystemComponent{
public:
//some functions related to operations for OS
virtual WindowHandle CreateNewWindow(/*...*/) = 0;
virtual void Show_Message(/*...*/) = 0;
//...
}
This is then inherited by another OS specific class, say for Windows its WindowsSystemComponent
:
#ifdef _WIN23
class WindowsSystemComponent : SystemComponent{
public:
virtual WindowHandle CreateNewWindow(/*...*/);
virtual void Show_Message(/*...*/);
//...
protected:
//Windows specific things...
}
#endif
This WindowsSystemComponent
then impliments the OS specific functions.
To create a System component in Windows, I do this:
WindowsSytemComponent* pWSystemComp = new WindowSystemComponent();
//...
//And the pass a pointer to this to the crossplatform code like this
pFrameWork->SetSystem((SystemComponent*)pWSystemComp);
where framework makes calls to the OS functions specified in SystemComponent
, and passes the pointer to whatsoever sub classes needs it.
What is needed:
I would like to remove the passing of pointers, and make the SystemComponent
class and the OS specific Functions implimentations acsessible to each object which wants to use them. Best way to do this was to make it a Singleton, but whin I try to do something like
virtual static SystemComponent* Instance() { /*...*/ };
inside the SystemComponent
class, which is abstract, i get a compiler error, saying such a thing is not allowed.
How then, should I go about it?
Upvotes: 0
Views: 1257
Reputation: 206607
Another way to deal with this is to emulate the notion of a singleton but let a derived class set the singleton to be used.
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;
When using WIN32, make sure WindowsSytemComponent
is a singleton and set the instance in the base class at initialization time.
SystemComponent::setInstance(WindowsSytemComponent::instance());
When using another platform, do the similar thing.
SystemComponent::setInstance(AnotherPlatformSytemComponent::instance());
Upvotes: 3
Reputation: 1863
You won't be able to instantiate a class that is abstract. The singleton pattern restricts the instantiation of a class to one object. This is in conflict with the previous constraint. You could better think of using the abstract factory pattern
Upvotes: 1
Reputation: 1056
This can't be done the way you are proposing. But What I think could solve your problem would be use of the factory pattern. Wikipedia
You could do something like this:
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;
}
};
Upvotes: 1
Reputation: 14786
You can't have a virtual static method, but the Instance method doesn't need to be virtual-- it just needs to create the right kind of SystemComponent for the platform you are running on. You just need to take the code you are using now to create the SystemComponent instance for the platform and put it in the Instance method.
Upvotes: 4