我最近被问到c ++中的单例设计模式。我不确切知道它的作用或何时需要,所以我试着用谷歌搜索它。我发现很多答案主要是在stackoverlow上,但我很难理解这些问题和答案中提到的代码。我知道单身人士应该满足以下属性,如果我错了,请纠正我。
It is used when we need to make one and only one instance of a class.
这在我的脑海中提出了以下问题
Does this mean that it can be created only once or does this mean that it can be
created many times but at a time only one copy can exist?
现在开始实施。 从here
复制class S
{
public:
static S& getInstance()
{
static S instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
private:
S() {}; // Constructor? (the {} brackets) are needed here.
// Don't forget to declare these two. You want to make sure they
// are inaccessible otherwise you may accidentally get copies of
// your singleton appearing.
S(S const&); // Don't Implement
void operator=(S const&); // Don't implement
};
请解释:
答案 0 :(得分:3)
1.为什么我们必须使getinstace()函数保持静态?
这是获取实例的唯一方法 - 静态意味着您不需要现有实例来调用它。如果你需要一个实例来获取一个实例,那么你将陷入鸡与蛋的关系。
那是因为它可以写静态:
S::getinstance().blah();
如果它不是静态的,你需要写
S& s_instance = ....
s_instance.getInstance().blah();
但是因为你已经有了一个实例,所以你不需要拨打getInstance
。如果获取实例的唯一方法是通过getInstance
?
2.为什么我们需要S(S const&);构造吗
你没有。它故意私有而未实现,因此调用它将导致错误。 如果它没有明确地变为私有而没有实现,编译器将为你创建一个默认的公共拷贝构造函数......这意味着人们可以写
S scopy(S::getInstance());
他们最终会得到一个新的S - 破坏单例语义的实例。
3. void operator =(S const&);做吗
相同2.它没有实现和私有,所以调用它将导致错误。如果你没有明确说明,编译器会为你创建一个默认的,在这种情况下,用户可以通过它获得一个新实例。
S scopy = S::getInstance();
4.为什么我们不实施最后两个功能?
如果您可以复制/分配单身,它将失去其单身人士身份。任何时候都只能存在一个单身人士。
但请注意,单例通常被视为反模式。没有非常充分理由你不想使用的东西。理解随之而来的线程问题也是明智的......然后最重要的是,你会遇到一些实现它的静态初始化命令惨败。 (代码中的方式没问题,但很容易出错。)
答案 1 :(得分:1)
1)是的。此功能可让您实际获得S
的单个实例。所以你打电话给S::getInstance()
。如果它不是静态的那么你将无法做到这一点。
2,3和4)请注意,构造函数和operator=
是私有的。这是为了防止某人制作S
的另一个实例,从而使单身人士状态无效。
您应该使用S
来获取单个实例,而不是构建自己的S::getInstance()
。
答案 2 :(得分:1)
是的,它应该是静态的,因为它不需要实例指针。使其成为非静态的将是徒劳的。
是的,我们至少需要一个功能构造函数。初始实例需要以某种方式进行。创建第一个实例时,私有构造函数将强制外部用户通过getInstance
获取实例。
当您为此实例分配新值时,将使用赋值运算符operator=(S const&)
。对于单例是没有意义的,因此被声明为私有而没有实现。没有人可以使用它。
不,复制构造函数和赋值运算符必须是私有的,没有实现。这是一个C ++习语,意思是:此类不能复制,也不能分配给。