在Singleton模式中,为什么我们必须使用静态对象而不是全局对象?
我尝试了以下
class Singleton;
Singleton* instance1 = NULL;
class Singleton
{
private :
Singleton()
{
}
//static Singleton* instance1;
public:
static Singleton* getinstance()
if(instance1== NULL)
{
instance1 = new Singleton();
}
return instance1;
void Dispaly()
{
}
~Singleton()
{
}
};
当我编译这段代码时,我得到错误“instance1的多重定义”
任何人都可以给出合理的理由吗?
答案 0 :(得分:4)
如果你把它作为一个全局对象,那么每个人都可以访问它,任何人都可以在不调用getInstance()
的情况下使用它。如果是这样,那么getInstance()
的目的是什么呢?第一次,您将调用它来创建实例,然后您不需要拨打getInstance()
,因为在第一次通话后,您可以直接使用instance
。
private
静态实例可让您更好地控制如何访问它:仅通过调用getInstance()
。
现在为什么在编译代码时会出现multiple definition of instance
错误?这是因为您已经在头文件本身中定义了全局对象,该文件包含在多个.cpp
文件中。这会导致对象的多个定义,每个翻译单元中的一个定义(。obj
文件)。
你实际应该做的是:
//Singleton.h
class Singleton
{
private :
Singleton();
Singleton(const Singleton &);
~Singleton();
static Singleton* instance; //declaration of static member!
public:
static Singleton* getInstance();
//..
};
然后将static
文件中的.cpp
成员定义为:
//Singleton.cpp
Singleton *Singleton::instance = 0; //definition should go in .cpp file!
Singleton::Singleton() {}
Singleton* Singleton::getInstance()
{
if ( instance == 0 ) instance = new Singleton();
return instance;
}
//...
答案 1 :(得分:4)
回答你的直接问题:
您收到错误消息的原因是因为您在头文件中定义了一个变量(好吧,无论如何,这是我的猜测)。因此,每当您#include
该头文件时,该变量将被重新定义。
总之,在头文件中定义变量几乎没有充分的理由。
[旁注:正如其他人所解释的那样,这是单例模式的一个非常糟糕的实现。]
答案 2 :(得分:3)
如果将此标题包含在多个文件中,您将获得每个文件中指针的副本。
这可能是链接器抱怨的内容。
答案 3 :(得分:0)
这是一个非常糟糕的单例实现。您应该使用已经存在的实现。它们中有很多......你的错误就会消失。
例如,有人可以设置instance = NULL;
。这样做可以实例化多个实例。
答案 4 :(得分:0)
这违背了单身人士的目的 - 从一个地方访问对象。您可以在任何地方访问它,而无需调用getInstance()。
至于错误,我的猜测是你将标题包含在多个文件中。
把
#pragma once
在头文件的开头,应解决错误。
但同样,这是单例模式的糟糕实现。
编辑:
或者使用标题保护:
#ifndef _SINGLETON_CLASS_INCLUDED
#define _SINGLETON_CLASS_INCLUDED
//// contents of your header
#endif
答案 5 :(得分:0)
将instance1的定义放在cpp文件中,将extern放在标题中。
然而,正如您已注释掉的那样,使用静态类成员会更为典型。 您只需要在cpp文件中定义它:
Singleton* Singleton::instance1 = 0;
答案 6 :(得分:0)
在Singleton模式中,为什么我们必须使用静态对象 而不是一个全球性的对象?
静态对象是您的类的私有成员,除Singleton类外,没有人可以访问它。这是C ++和其他OOP语言中的基本封装原则。
答案 7 :(得分:0)
假设这是头文件的一部分,那么对于包含它的每个翻译单元,您将获得instance1
的一个定义,因此如果多个包含它,则会出现多重定义错误。无论是全局成员还是静态成员,都会遇到这个问题。
要修复错误,您需要在头文件中声明extern Singleton * instance1;
,如果您希望它由于某种原因是全局的,或者如果您想要阻止对它的任意访问,则需要私有静态成员声明),然后是源文件中的定义。
或者,您可以将实例设置为getinstance()
中的静态本地对象,这将修复内存泄漏,并且至少在C ++ 11中会出现线程安全问题:
static Singleton & getinstance()
{
static Singleton instance;
return instance;
}
或者你根本不能使用单身人士 - 这几乎肯定不是一个好主意。