【问题标题】:how can a base class disable the derived class's constructor基类如何禁用派生类的构造函数
【发布时间】:2012-12-24 18:03: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 的 ctor 设为私有并将 Singleton 声明为朋友,但是我有什么办法可以在基类中做到这一点,因此仅派生而不声明任何 ctor 就足以使类单例?

【问题讨论】:

  • 这源于你可以使用base的构造函数:liveworkspace.org/code/3iuwiB%242
  • 是的,我可以将 Singleton 的 ctor 声明为私有,但随后编译器在“new T”处出错。当然,MySingleton 的构建也是不可能的,所以我非常喜欢这个解决方案,如果它可以编译:)
  • 是的,我也这么认为,除此之外应该有办法(我也已经把它放到了问题中:))
  • 那将是我在再次发布罢工之前无法正确阅读内容:p
  • 我想你要找的词是protected

标签: c++ templates inheritance singleton


【解决方案1】:

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

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 单例)

【讨论】:

    猜你喜欢
    • 2016-07-19
    • 2018-07-16
    • 2018-07-21
    • 2015-08-18
    • 1970-01-01
    • 2014-03-26
    • 2016-12-20
    • 1970-01-01
    • 2011-05-03
    相关资源
    最近更新 更多