Should we declare the desctructor of a Singleton class as private? - c++

Providing the simple implementation of a Singleton class below. It is possible for anybody to call the destructor as long as s/he has the reference to the singleInstance.
class SomeClass {
public: /** Singleton **/
static SomeClass &instance() {
static SomeClass singleInstance;
return singleInstance;
};
private:
SomeClass() = default;
SomeClass(const SomeClass&) = delete;
SomeClass &operator=(const SomeClass&) = delete;
};
To prevent such a nonsense operation, should we declare the destructor of Singleton classes in a private context?
class SomeClass {
// ... same above
private:
~SomeClass() {}
};
The problem exists also for the heap-allocated Singleton instances. Consider the implementation below.
class SomeClass {
public: /** Singleton **/
static SomeClass &instance() {
static SomeClass *singleInstance = nullptr;
if(!singleInstance) {
singleInstance = new SomeClass;
}
return *singleInstance;
};
private:
SomeClass() = default;
SomeClass(const SomeClass&) = delete;
SomeClass &operator=(const SomeClass&) = delete;
// ~SomeClass() {}
};
int main()
{
SomeClass *const ptr = &SomeClass::instance();
delete ptr; // Compiles if destructor isn't private and vice versa
return 0;
}

Should we declare the desctructor of a Singleton class as private?
Yes.
Sidenote: Singleton pattern is rarely necessary, an using it unnecessarily is a common anti pattern.

Related

What's the preferred way to instantiate one class in another?

Pretty basic question. Has to do with design preference but I think there are some caveats that I'm missing.
I want to have an instance of some class inside another class. The way I see it, I have 3 options:
Have the object class2 inside class1 as I have it below. This means it gets constructed when an instance of class1 gets constructed. My issue here is that it may need a default and/or copy constructor? When I instantiate a class1 object below, does it construct class2_inst(args) using that constructor? Or is class2_inst already created with some default constructor and the line class2_inst(args) simply copies an anonymous class2 object?
class class2 {
public class2(args) {
...
}
}
class class1 {
protected class2 class2_inst;
public class1(args) : class2_inst(args) {
...
}
}
I can have a pointer to class2:
class class2 {
public class2(args) {
...
}
}
class class1 {
protected class2* class2_inst;
public class1(args) {
class2_inst = new class2(args);
...
}
}
This has the advantage that class2 isn't instantiated until I explicitly call the new operator.
Then there's using a reference instead of a pointer:
class class2 {
public class2(args) {
...
}
}
class class1 {
protected class2& class2_inst;
public class1(args) {
class2_inst = new class2(args);
...
}
}
I want class2_inst's life-time to match that of class1. No funny business with having class2_inst living outside of class1. So references may be the way to go.
Of the 3 methods, which is everyone's preferred way, and why?
Your examples are a bit backwards. I think you meant this instead:
class class2 {
public:
class2(args) {
...
}
};
class class1 {
protected:
class2 class2_inst;
public:
class1(args) : class2_inst(args) {
...
}
};
class class2 {
public:
class2(args) {
...
}
};
class class1 {
protected:
class2* class2_inst;
public:
class1(args) {
class2_inst = new class2(args);
...
}
};
class class2 {
public:
class2(args) {
...
}
};
class class1 {
protected:
class2& class2_inst;
public:
class1(args) {
class2_inst = new class2(args);
...
}
};
Now, that being said:
Example 1 will work nicely for what you want, and is the preferred way to go: "I want class2_inst's life-time to match that of class1. No funny business with having class2_inst living outside of class1." And to answer your question - yes, class2_inst(args) will construct the class2_inst member directly, not default-construct it and then copy an anonymous class2 object into it. See Constructors and member initializer lists.
Example 2 will also work, but to make it work correctly, you need to add a destructor to class1 to delete the new'ed class2 object, and you need to also add copy/move constructors and copy/move assignment operators to class1 to copy/move class2 objects properly, per the Rule of 3/5/0.
class class2 {
public:
class2(args) {
...
}
};
class class1 {
protected:
class2* class2_inst;
public:
class1(args) {
class2_inst = new class2(args);
...
}
class1(const class1 &src) {
class2_inst = new class2(*(src.class2_inst));
...
}
class1(class1 &&src) {
class2_inst = src.class2_inst;
src.class2_inst = nullptr;
...
}
~class1(args) {
delete class2_inst;
}
class1& operator=(const class1 &rhs) {
if (this != &rhs) {
class1 tmp(rhs);
std::swap(class2_inst, tmp.class2_inst);
}
return *this;
}
class1& operator=(class1 &&rhs) {
class1 tmp(std::move(rhs));
std::swap(class2_inst, tmp.class2_inst);
return *this;
}
};
You get all of that functionality for free in Example 1, as the compiler will auto-generate those extra methods for you. Yes, there are valid cases where it makes more sense to use pointers for members, but this example is not one of them.
Example 3 is simply not valid. You can't assign an object pointer to an object reference. And why would you think "references may be the way to go"? They are not, in this case.
So, in a nutshell, you should prefer value sematics whenever possible, but use pointer/reference semantics when needed.

CRTP - Is it possible to make an abstract base class?

I'm implementing a static polymorphism:
template<typename T>
class Base {
public:
void method() {
// do something
impl();
// do something else
}
void impl() { // intended to be private
static_cast<T*>(this)->impl();
}
};
class Derived : public Base<Derived> {
public:
void impl() { // intended to be private
}
};
This code is a static implementation of a dynamic polymorphic classes where void impl() was pure virtual. So the base class was abstract.
Now these classes implement static polymorphism and therefore don't have pure virtual functions.
Is it possible to make Base class abstract, so that objects of this class can't be created?
You can use a protected destructor and constructors:
template<typename T>
class Base {
public:
void method() {
// do something
impl();
// do something else
}
void impl() { // intended to be private
static_cast<T*>(this)->impl();
}
protected:
Base() = default;
~Base() = default;
// If you don't want to implement proper copying/moving:
// Base(const Base&) = delete;
// Base(Base&&) = delete;
// Base& operator=(const Base&) = delete;
// Base& operator=(Base&&) = delete;
};
This will even disallow a derived class's member functions to create base class objects, as well as trying to delete a pointer whose static type is Base<T>.

Reinitialize all member variables in derived class only

I have two classes:
class NonCopyable {
private:
int key;
protected:
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator = (const NonCopyable &) = delete;
};
class Derived : public NonCopyable {
private:
std::vector<int> numbers;
float f;
int* ptr;
public:
Derived() : f(5.0f), ptr(nullptr) {}
~Derived();
};
Now, I'd like to reinitialize all the values in the Derived class and call the appropriate destructors. That is, the NonCopyable class should not be touched, but the Derived class should be changed as if it was newly initialized.
What is the simplest way of achieving this goal? I am trying to avoid making a member function which manually reinitializes every member variable.
Clearly, I can not use the following approach:
Derived d;
// [...] many changes to d
d = Derived();
because the copy constructor is deleted from the NonCopyable class and the fact that it would change the member variables of NonCopyable had this not been the case.
It becomes much easier if you move your private data to a separate aggregate:
struct DerivedData {
std::vector<int> numbers;
float f = 5.0;
int* ptr = nullptr;
};
class Derived : public NonCopyable {
DerivedData data;
public:
~Derived();
void reset() { data = DerivedData(); }
};

Inherit Singleton

Quick question. Is there anyway to inherit a singleton so that the child class is a singleton? I have searched around but every singleton I can find is implemented per class, and not in a generic fashion.
Yes there is a generic way. You can implement a Singleton via CRTP, like:
template<typename T>
class Singleton
{
protected:
Singleton() noexcept = default;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
virtual ~Singleton() = default; // to silence base class Singleton<T> has a
// non-virtual destructor [-Weffc++]
public:
static T& get_instance() noexcept(std::is_nothrow_constructible<T>::value)
{
// Guaranteed to be destroyed.
// Instantiated on first use.
// Thread safe in C++11
static T instance{};
return instance;
}
};
then derive from it to make your child a Singleton:
class MySingleton: public Singleton<MySingleton>
{
// needs to be friend in order to
// access the private constructor/destructor
friend class Singleton<MySingleton>;
public:
// Declare all public members here
private:
MySingleton()
{
// Implement the constructor here
}
~MySingleton()
{
// Implement the destructor here
}
};
Live on Coliru
A singleton has a static getInstance() method that upon first invocation creates the single instance of the class, and therefore is statically-bound to the type of singleton class being instantiated. I don't see the immediate utility of having a Singleton hierarchy. But if you insist on having one, you might consider making the getInstance method virtual and overriding it in the class extending your parent Singleton.
class Singleton {
public virtual Singleton * getInstance() const
{
// instantiate Singleton if necessary
// return pointer to instance
}
...
};
class MySingleton : public Singleton {
// overrides Singelton's getInstance
public virtual MySingleton * getInstance() const
{
// instantiate MySingleton if necessary
// return pointer to instance
}
};
Of course, a robust implementation would store and return smart pointers.

Prevent instantiation of an object outside its factory method

Suppose I have a class with a factory method
class A {
public:
static A* newA()
{
// Some code, logging, ...
return new A();
}
}
Is it possible to prevent the instantiation of an object of this class with a new, so that factory method is the only method to create an instance of the object?
Sure; just make the constructor private (protected if this is a base class):
class A {
public:
static A* newA()
{
// Some code, logging, ...
return new A();
}
private:
A() {} // Default constructor
};
You should make the copy constructor private/protected as well, if required.
And as always, you should strongly consider returning a smart pointer rather than a raw pointer, in order to simplify memory management issues.
You may also want to make the copy constructor private as well or with new C++11 syntax you can explicitly tell the compiler to not copy it and make the default constructor private with something like this:
struct NonCopyable {
NonCopyable & operator=(const NonCopyable&) = delete;
NonCopyable(const NonCopyable&) = delete;
NonCopyable() = default;
};
class A : NonCopyable {
public:
static std::shared_ptr<A> newA()
{
// Some code, logging, ...
return std::make_shared<A>();
}
private:
A() {} // Default constructor
};
The C++03 way was usually something like this:
class A {
public:
static A* newA()
{
// Some code, logging, ...
return new A();
}
private:
A() {} // no outsider default constructor
A(const A& rhs); // no copy
A& operator=(const A& rhs); // no assignment
};
int main()
{
A x; // C2248
A y(x); // C2248
x = y; // C2248
A* p = A::newA(); // OK
std::cin.get();
return 0;
}