Reputation:
Considering the following design for singleton pattern from yolinux (http://www.yolinux.com/TUTORIALS/C++Singleton.html)
#include <string>
class Logger{
public:
static Logger* Instance();
bool openLogFile(std::string logFile);
void writeToLogFile();
bool closeLogFile();
private:
Logger(){}; // Private so that it can not be called
Logger(Logger const&){}; // copy constructor is private
Logger& operator=(Logger const&){}; // assignment operator is private
static Logger* m_pInstance;
};
would someone explain why Logger(Logger const&){};
and Logger& operator=(Logger const&){};
are required here?
Thanks in advance.
Upvotes: 1
Views: 1066
Reputation: 3604
If you force the copy constructor and the assignment operators to be private then you won't be able to compile assignment of two Logger objects.
This will result in a linker error, which is not an explicit message. These methods are generated by default so you have to force them to be private
In C++11 they use the deleted methods to have a clearer message
Logger(Logger const&)=delete; // copy constructor does not exist
Logger& operator=(Logger const&)=delete; // assignment operator does not exist
The delete is not compulsory and the singleton works well without this feature so if you don't have this supported in your compiler you can just make it private it will work. This feature gives explicit errror messages but does not affect the behaviour of the singleton itself.
For more info about delete feature you can have a look here:
Meaning of = delete after function declaration
You can also prevent the object from being destroyed by making the destructor private.
What is the use of having destructor as private?
Upvotes: 3
Reputation: 1362
The traditional solution to achieve singleton behavior is to declare constructor private. The copy constructor and assignment operator (which intentionally have no implementations) are declared private to prevent any sort of copies being made
•Because they are private, this will lead to a compile-time error from anyone trying to use them that has not access to the private parts of the class.
•Which leaves friends (and the class itself) for which the error will occur under the form of undefined symbol, either at link-time (if you check for those there) or most probably at run-time (when trying to load the library).
Upvotes: 1
Reputation: 37608
Those are copy constructor and copy assignment operator. If they weren't defined as private they would be automatically generated as public and the instance would be copyable which contradicts the Singleton pattern.
Since the C++11 standard you could also use:
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
this syntax is perhaps clearer and also ensures that the object can't be copied even by friends and private members.
Upvotes: 1
Reputation: 14184
The copy constructor and the lvalue assigment operator are declared as private to make the type non-copyable.
On the other hand I encourage you to use the Meyers singleton instead of the dynamic-memory based: Its far easier to implement, not leaks (Note being strict that your singleton leaks memory, the instance is never deleted), and is thread-safe as defined in the C++11 standard memory model:
T& instance()
{
static T _instance;
return _instance;
}
Upvotes: 1
Reputation: 7160
The comments explain this quite nicely.
If you didn't explicitly define the constructor and copy constructor, then they will be created by default as public. By defining them here, you are making sure they are private, and so can never be called by the user.
Upvotes: 1
Reputation: 64356
From your link:
This design pattern and methodology ensures that only one instance of the C++ class is instantiated.
Logger(Logger const&)
is a copy constructor which allows to copy object. And this is wrong by idea.
Logger& operator=(Logger&)
also allows to copy object.
Upvotes: 1