how to answer this question?
views:
206answers:
6This is not a particularly great idea from two standpoints.
First, if you have a pre-existing class that already has exactly what you need in a singleton, you can just declare:
MyClass singletonObject;
Then you don't need to modify it at all.
Second, it's not all that likely that your class is, in fact, exactly what you need. Concurrency issues spring to mind as a likely problem.
If you represented a singleton as a static class, you would not be able to pass your singleton instance as a function argument, or store a reference to it in a variable.
EDIT:
Oops, the answer no. As others have pointed out, simply setting all methods/members to static follows the Monostate pattern (of which I was not aware). I was too eager to show off my shiny Singleton template (a simplified version of Alexandrescu's SingletonHolder, really).
This answer should be downvoted.
Original Answer:
Yes. But it is less flexible than other ways of designing singletons. See Modern C++ Design by Alexandrescu and his Loki library: http://en.wikipedia.org/wiki/Loki_%28C%2B%2B%29
If you have several static singletons that depend on each other and on other global objects, you risk having problems because the order of their initialization (before main() kicks in) is tricky and can lead to unexpected results.
Using templates, you can convert normal classes into singletons. If you later decide that your singleton is no longer a singleton (i.e. you can have multiple instances), then you don't have to convert all the class's methods to non-static.
One way, using templates, is something like this:
template <class T>
class Singleton
{
public:
static T& instance()
{
static T singleton;
return singleton;
}
private:
Singleton() {} // Disallow construction of Singleton<T> instances
}
class Foo
{
public:
void print() {std::cout << "Hello world\n";}
};
typedef Singleton<Foo> TheFoo;
main()
{
TheFoo::instance().print();
}
Note that this does not prevent you from creating Foo instances, unless you make the Foo constructor private (and make Singleton a friend of Foo).
An advantage with this method over all-static classes is that you have more control over when the singleton object is constructed. It'll be constructed the first time you access the singleton. So you can have something like this:
main()
{
TheFoo::instance(); // Make sure the Foo is constructed before the Bar
TheBar::instance();
}
There is debate over of the appropriateness of Singletons. Some say they are global objects in disguise and can make your code less reusable. I will not comment further on that, as I have not made up my mind myself.
EDIT:
If you find TheFoo::instance() too verbose, you can always provide an inline shortcut function or use references:
inline Foo& theFoo() {return TheFoo::instance();}
main()
{
theFoo().makeMeSomeCoffee("1 milk, 1 sugar");
Foo& foo = theFoo();
foo.makeMeASandwich("BLT");
}
Mmmm.... off to make coffee & sandwich.
Andrei Alexandrescu talks about this briefly in Modern C++ Design.
He outlines two disadvantages to the monostate pattern:
- Static functions cannot be virtual.
- Initialization and cleanup is not central.
Number 1 means extending or changing the class might be made more difficult. Number 2 makes it difficult to track the life-time of data.
The monostate pattern and the singleton pattern solve two different but close problems. The monostate pattern makes sure all instances of the class operate on the same data, while a singleton makes sure here is only of instance of the class to operate with.
My personal way to design a singleton is thus:
// header
class MySingleton
{
public:
static int Get();
static void Set(int i);
private:
struct Impl;
static Impl& Instance();
}; // class MySingleton
// source
struct MySingleton::Impl { int m_data; };
MySingleton::Impl& MySingleton::Instance()
{
static Impl M_Instance;
return M_Instance;
}
int MySingleton::Get() { return Instance().m_data; }
void MySingleton::Set(int i) { Instance().m_data = i; }
It is, in fact, reminiscent of the Pimpl idiom, adapted to static use.
Here, I can extend the interface at leisure (ie adding new methods) without breaking the binary/source compatibility (taking care about overloads), which is quite nice.
And it simplifies the client code:
// Classic
int i = MySingleton::Instance().get();
// static interface
int i = MySingleton::Get();
For the same effect, I consider it a bother to actually force the client to go through the call to Instance each and every time she wishes to call a method. Also note that by taking care myself about the initialization order fiasco, I don't force my client to bother about it, which is nice too!
Similarly, I loathe people who use this signature for Instance before making it public:
static MySingleton* Instance();
Why returning a pointer when a reference will do ? Should I expect it to be null ? If not then why using a pointer ? And it's more typing to use it too... (-> instead of .)
As a summary:
- static interface
- single static "state" attribute, grouping all the implementation details, and instantiated with care as to avoid the initialization order fiasco
A bit different approach :
template <typename T>
T & getSingleton() {
static T singleton;
return singleton;
}
Foo & f = getSingleton<Foo>();