Глобальный объект в синглтоне - PullRequest
0 голосов
/ 18 августа 2011

В шаблоне 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 ]

4 голосов
/ 18 августа 2011

Чтобы ответить на ваш прямой вопрос:

Причина, по которой вы получаете сообщение об ошибке, заключается в том, что вы определяете переменную в заголовочном файле (ну, я думаю, в любом случае)Таким образом, каждый раз, когда вы #include используете этот заголовочный файл, переменная будет переопределяться.

Таким образом, почти никогда не существует веской причины для определения переменных в заголовочных файлах.[Примечание: как объяснили другие, это очень плохая реализация шаблона синглтона.]

4 голосов
/ 18 августа 2011

Если вы сделаете его глобальным объектом, то каждый сможет получить к нему доступ, и любой может использовать его, не вызывая getInstance().Если так, то какова цель getInstance() тогда?В первый раз вы будете вызывать его для создания экземпляра, затем вам не нужно будет вызывать getInstance(), поскольку после первого вызова вы можете напрямую использовать instance.

A private *Экземпляр 1008 * static дает вам больше контроля над тем, как к нему можно получить доступ: только путем вызова 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;
 }
 //...
3 голосов
/ 18 августа 2011

Если вы включите этот заголовок в несколько файлов, вы получите копию указателя в каждом файле.

Вероятно, именно на это жалуется компоновщик.

0 голосов
/ 18 августа 2011

Предполагая, что это часть заголовочного файла, вы получите одно определение instance1 для каждой единицы перевода, которая его включает, и, таким образом, ошибка множественного определения, если его включает более одного. Вы получите эту проблему, будь то глобальный или статический член.

Чтобы исправить ошибку, вам нужно объявление в файле заголовка (extern Singleton * instance1;, если вы хотите, чтобы оно было глобальным по какой-то причине, или объявление частного статического члена, если вы хотите предотвратить произвольный доступ к нему), а затем определение в исходном файле.

В качестве альтернативы, вы можете сделать экземпляр статическим локальным объектом в getinstance(), что устранит утечку памяти и, по крайней мере, в C ++ 11, проблему безопасности потока:

static Singleton & getinstance()
{
    static Singleton instance;
    return instance;
}

Или вы не могли бы использовать синглтон вообще - это почти наверняка не очень хорошая идея.

0 голосов
/ 18 августа 2011

В шаблоне Singleton почему мы должны использовать статический объект, а не глобальный объект?

Статический объект является частным членом вашего класса, и никто не имеет к нему доступа, кромеСинглтон класс.Это базовый принцип инкапсуляции в C ++ и других языках ООП.

0 голосов
/ 18 августа 2011

Поместите определение instance1 в файл cpp и extern в заголовок.

Хотя было бы более типичным использовать статический член класса, как вы уже прокомментировали.Вам просто нужно определить его в файле cpp:

Singleton* Singleton::instance1 = 0;
0 голосов
/ 18 августа 2011

Это побеждает цель единственного - доступ к объекту из одного места. Вы можете получить к нему доступ везде, не вызывая getInstance ().

Что касается ошибки, я думаю, вы включили свой заголовок в несколько файлов.

Помещенный

#pragma once

в начале вашего заголовочного файла, который должен устранить ошибку.

Но опять же, это плохая реализация шаблона синглтона.

EDIT:

Или используйте охрану заголовка:

#ifndef _SINGLETON_CLASS_INCLUDED
#define _SINGLETON_CLASS_INCLUDED

//// contents of your header

#endif
0 голосов
/ 18 августа 2011

Это очень плохая одиночная реализация. Вы должны использовать реализацию, которая уже здесь. Их много .. и ваша ошибка исчезнет.

Например, кто-то может установить instance = NULL;. Делая это, вы можете создать несколько экземпляров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...