单身中的全局对象

时间:2011-08-18 11:06:57

标签: c++ singleton

在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的多重定义”

任何人都可以给出合理的理由吗?

8 个答案:

答案 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;
}

或者你根本不能使用单身人士 - 这几乎肯定不是一个好主意。