基类如何禁用派生类的构造函数

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

本文关键字:构造函数 派生 何禁用 基类      更新时间:2023-10-16

我试着写一个单例类,这样一个类只需要从它派生,并自动成为单例:

基类:

 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;

派生类:

#include <iostream>
#include "Singleton.h"
class MySingleton : public Singleton<MySingleton>
{
public:
    void helloWorld(void)
    {
        printf("Hello, World!n");
    }
};
主:

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

这工作完美,但它不是一个真正的单例,因为我仍然可以使用它的默认构造函数构造MySingleton。当然,我可以将MySingleton的函数设为私有,并将Singleton声明为友例,但是否有办法在基类中做到这一点,以便仅仅派生而不声明任何函数就足以使类成为单例?

由于基类模板必须构造单例对象,因此它需要访问具体类的构造函数。因此,该构造函数应该是public的,或者基类必须是具体类的友类。每个人都可以访问具体类中的公共actor,因此您不能在编译时禁止它的使用。但是,您可以确保它只在运行时被调用一次:

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;

指出:-我在这里使用的instantiating变量不是线程安全的instantiating的真/假设置不是异常安全的(newT::T()可能会抛出)-使用指针作为实例变量是不安全的,容易发生内存泄漏。考虑使用shared_ptr或引用(Meyers单例)