I just wondered what the best way is to get rid of the globally available static getInstance() in a Singleton. I do not want my Singleton classes being accessed from every point in my program.
I thought about maybe having a create() public static function that creates one object and returns it but one cannot call this method twice.
But it's not very elegant for me. Than I would have to make an assertion or throw an exception in case create() gets called a second time.
Is there any other way I can achieve what I want?
You said that "creating one a second time would damage the whole application.". My response is: so don't make more then one. In C++, the type system is too weak to easily ensure this at compile-time. We can still write up a utility to approximate it at run-time, though.
Note, though, that this in no way implies you should use a singleton. (You have zero need for a global; it's unfortunate the drones have associated single-instance with global). What you want is this:
#include <stdexcept>
// inherit from this class (privately) to ensure only
// a single instance of the derived class is created
template <typename D> // CRTP (to give each instantiation its own flag)
class single_instance
{
protected: // protected constructors to ensure this is used as a mixin
single_instance()
{
if (mConstructed)
throw std::runtime_error("already created");
mConstructed = true;
}
~single_instance()
{
mConstructed = false;
}
private:
// private and not defined in order to
// force the derived class be noncopyable
single_instance(const single_instance&);
single_instance& operator=(const single_instance&);
static bool mConstructed;
};
template <typename T>
bool single_instance<T>::mConstructed = false;
Now you get an exception if the class is constructed more than once:
class my_class : private single_instance<my_class>
{
public:
// usual interface (nonycopyable)
};
int main()
{
my_class a; // okay
my_class b; // exception
}
Remove the Singleton and re-insert the enclosed function to where it should actually be, with appropriate access modifiers.
See here for a definitive list of reasons why singletons are an antipattern.
Especialy important - see here for the different between Singleton (the GoF pattern) and singleton (as in 'there is one and only one of me').
You could make your getInstance()
method protected, and allow access via friend
declarations. You'll have to manually "whitelist" classes with access to getInstance()
both by adding a friend
declaration.
class Singleton {
protected:
static Singleton* getInstance() { return Singleton::s_instance_; }
// Allow access to SingletonUser
friend class SingletonUser;
private:
Singleton() { }
static Singleton* s_instance_;
};
class SingletonUser {
public:
void doStuff() {
// Fails if not a friend of Singleton
Singleton* s = Singleton::getInstance();
}
};