设计一个只有一个可能实例的类/类型 - C ++

时间:2012-10-08 19:28:48

标签: c++ class types

我希望class T只能在整个程序中生成1个实例。

现在我知道std::unique_ptr,但有两个问题:

  • 它仅限于范围(但这不是一个大问题......)
  • 它需要显式使用,这意味着它不是类或类型的一部分,它只是和处理程序和一个特殊的指针,但它不会修改我的类的设计。

现在我希望class T设计的方式甚至不会错误地用户可以在同一个程序中声明2个实例,而且我不能依赖于我的用户将声明{{{ 1}} std::unique_ptr因为我想通过设计解决这个问题。

现在我只考虑如何以优雅的方式隐式使用T,问题是我目前没有任何线索。

另一种方法是检查这个班级是否由unique_ptr处理,但这项检查会让我在表演方面失去优势。

因为只有一个实例非常重要,所以在我的情况下我只看到两个选项:1)尝试通过设计解决这个问题2)在编译时使用某种检查/宏来抛出错误。

我知道这看起来微不足道但是设计方法不是,至少对我而言,请帮助。

3 个答案:

答案 0 :(得分:4)

您正在寻找的是Singleton模式,虽然它被许多人(包括我自己)广泛认为是anti-pattern,但我仍然会向您展示所需的基本元素建立一个。

基本上你需要做的是提供三件事:

  1. 一个static方法,“获取”唯一的实例
  2. 一个private构造函数,以便任何人都无法实例化它
  3. (可选)在main启动之前创建唯一实例的方法
  4. 以下是基本代码:

    class Singleton
    {
    public:
      Singleton&  get() 
      { 
        static Singleton me_;
        return me_;
      }
    private:
      Singleton() {};
    };
    

    我留给你发现如何实现上面的#3,以及为什么你不应该首先使用Singleton - 有很多原因。

答案 1 :(得分:3)

这通常被称为单身人士。

请参阅http://en.wikipedia.org/wiki/Singleton_pattern

C ++中的典型技巧是拥有一个通过引用返回单例实例的函数,并使构造函数变为私有。

类似的东西:

#include <iostream>
using namespace std;

class Foo
{
private:
  Foo() : a(3) { a++; }
  static Foo singleton;
  int a;
public:
  static Foo& getFoo() { return singleton; }
  void doStuff() { cout<<"My a is: "<<a<<endl; }
};

Foo Foo::singleton;

int main(int argc, char** argv)
{
  Foo::getFoo().doStuff();
  Foo &foo = Foo::getFoo();
  foo.doStuff();

  //uncomment below to cause compile error                                                                                                                                                                                                                                                                                                                                
  //Foo foo2;                                                                                                                                                                                                                                                                                                                                                             
}

请注意,在实际代码中,您将其拆分为标头和cpp文件。在那种情况下

Foo Foo::singleton;

部分必须进入cpp文件。

答案 2 :(得分:2)

你至少可以

 static int count;
 assert(count == 0);
 count++;

在单例类的构造函数中。这不能确保在编译时你的类是单例,但至少它会在运行时检查它。

你也可以使构造函数变为私有,并且有一个静态成员函数返回(一次)一个指向你的实例的指针,可能就像

 class Singleton {
 private:
    Singleton() {
      static int count;
      assert(count == 0);
      count++;
    };
    Singleton(Singleton&) = delete;
 public:
    static Singleton* the_instance() {
      static Singleton* it;
      if (!it) it = new Singleton();
      return it;
    }
 };