简体   繁体   中英

how can a base class disable the derived class's constructor

I try to write a singleton class so that a class only needs to derive from it and be automatically singleton:

Base class:

 template <class T>
 class Singleton
 {
 private:
     static T* instance;
 public:

     static T* getInstance(void)
     {
         if(!instance)
             instance = new T;
         return instance;
     }

     static void release(void)
     {
         if(instance)
         {
             delete instance;
             instance = NULL;
         }
     }
 };

 template <class T>
 T* Singleton<T>::instance = NULL;

My derived class:

#include <iostream>
#include "Singleton.h"

class MySingleton : public Singleton<MySingleton>
{
public:
    void helloWorld(void)
    {
        printf("Hello, World!\n");
    }
};

main:

int main(int argc, const char * argv[])
{
    MySingleton* s = MySingleton::getInstance();
    s->helloWorld();
    return 0;
}

This works perfectly, but it's not a real singleton, since i can still construct MySingleton using it's default constructor. I can, of course, make MySingleton's ctors private and declare Singleton a friend, but is there any way i can do that in the base class, so that just deriving and not declaring any ctors is enough to make a class singleton?

Since your base class template has to construct the singleton object, it needs access to the concrete class' constructor. Therefore, that constructor should be either public or the base class has to be a friend of the concrete class. A public Ctor in the concrete class is accessible by everyone, so you can not prohibit its use at compile time. You can, however, assure, that it is only called once, at run time:

template <class T>
class Singleton
{
  /* ... */
  static bool instantiating;
protected:
  Singleton()
  {
    if (!instantiating) //not called in instance() function
      throw std::runtime_error("Don't call me!");
  }

public:
  static T* getInstance()
  {
    intantiating = true;
    instace = new T();
    instantiating = false;
  }
};

template <class T>
bool Singleton<T>::instantiating = false;

Notes: - The instantiating variable as I use it here is not threadsafe - The true/false setting of instantiating is not exceptionsafe ( new or T::T() might throw) - Your use of a pointer as instance variable is insecure and prone to memleaks. Consider using shared_ptr or a reference (Meyers singleton)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM