Keeping the single in Singleton

As we've mentioned previously, one of the most important parts of the Singleton pattern is the fact that there is only one of those objects. That causes some issues with the original code that we've written, namely that with some simple usage of C++ it is quite easy to have more than one of these classes created by other programmers on your team. First and most obviously, they can just create a Singleton variable (a variable of type Singleton) like the following:

Singleton singleton;

In addition, as a higher-level programming language, C++ will try to do some things automatically for you when creating classes to eliminate some of the busy work that would be involved otherwise. One of these things is automatically creating some functionality between classes to enable you to create or copy objects of a custom class that we refer to as a constructor and copy constructor. In our case, you can also create a copy of your current object in the following way:

Singleton instanceCopy(*(Singleton::GetInstance()));

The compiler will also create a default destructor and an assignment operator, moving the data from one object to the other.

Thankfully, that's a simple enough thing to fix. If we create these functions ourselves (declaring an explicit version), C++ notes that we want to do something special, so it will not create the defaults. So to fix our problem, we will just need to add an assignment operator and some constructors that are private, which you can see in the bold code that we've changed:

class Singleton 
{
public:
static Singleton * GetInstance()
{
// If the instance does not exist, create one
if (!instance)
{
instance = new Singleton;
}

return instance;
}

private:
static Singleton * instance;

// Disable usability of silently generated functions
Singleton();
~Singleton();
Singleton(const Singleton &);
Singleton& operator=(const Singleton&);

};
If you are using C++ 11 or above, it is also possible for us to instead mark the functions we don't want to use as deleted, which would look like this:
Singleton() = delete;
~Singleton() = delete;
Singleton(const Singleton &) = delete;
Singleton& operator=(const Singleton&) = delete;
For more information on the delete keyword, check out http://www.stroustrup.com/C++11FAQ.html#default.

Another thing that may possibly be an issue is that instance is a pointer. This is because, as a pointer, our users have the ability to call delete on it and we want to make sure that the object will always be available for our users to access. To minimize this issue, we could change our pointer to be a reference, instead, by changing the function to the following (note the return type and that we use *instance now on the last line):

static Singleton& GetInstance() 
{
// If the instance does not exist, create one
if (!instance)
{
instance = new Singleton;
}

return *instance;
}

Programmers are used to working with references as aliases for objects that exist somewhere else in our project. People would be surprised if they ever saw something like:

Singleton& singleton = Singleton::GetInstance(); 
delete &singleton;

While technically doable, programmers won't expect to ever use delete on the address of a reference. The nice thing about using references is that, when you need them in code, you know that they exist because they're managed somewhere else in the code--and you don't need to worry about how they are used.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.54.136