Проблема реализации класса Singleton

В Code 1 объявлен статический указатель aSingletonClass *instance_ и статическая функция void deleteInstance( void ).

Я реализовал код 2 без использования статического указателя и статической функции (я думал, что синглтон можно сделать и без него, но я не уверен!!!)

Пожалуйста, сообщите мне, может ли это изменение быть опасным, и в этом случае моя программа может выйти из строя.

Код 1:

class aSingletonClass
{
public:

  static aSingletonClass *getInstance( void )
  {

    if(!instance_)
      instance_ = new aSingletonClass;
    return instance_;
  }

  static void deleteInstance()
  {
    if(instance_)
      delete instance_;
    instance_ = NULL; //important as this can create dead reference problems
  }

private:

  static aSingletonClass *instance_;

  aSingletonClass() {};

  ~aSingletonClass() {};
};

int main()
{
  aSingletonClass *someVar = NULL;

  someVar = aSingletonClass::getInstance();

  aSingletonClass::deleteInstance();

  return 0;
}

Код 2:

class A
{
    int x;
    A(int a)
    { x=a;  }

    ~A()
    { }

public:
     static A* start()
     {
       A* ptr1 = new A(3);
       return (ptr1);
     }


     void end()
     {
       delete this;
     }
};

int main()
{
  A* ptr=A::start();

  ptr->end();
}

person user436212    schedule 15.12.2010    source источник
comment
Какой беспорядок ... Я переработал некоторые части вопроса, но тьфу ...   -  person Matthieu M.    schedule 15.12.2010
comment
Ваша вторая реализация не является синглтоном. Я советую вам поискать в Интернете дополнительную информацию о шаблоне, его ограничениях и (многочисленных) реализациях.   -  person Tony    schedule 15.12.2010
comment
Если вы действительно чувствуете, что вам нужен синглтон, по крайней мере, убедитесь, что он не копируется (boost::noncopyable или сделайте объявления конструктора копирования и оператора присваивания закрытыми и не определенными)   -  person stefaanv    schedule 15.12.2010


Ответы (4)


Ваш код должен быть таким:

class A    {
  public:
    static A *getInstance( void )
    {
       if(!instance_)
          instance_ = new A();
       return instance_;
    }
    static void deleteInstance()
    {
        if(instance_)
           delete instance_;
        instance_ = NULL; //important as this can create dead reference problems
    }
    static A* start()
    {
        A* ptr1 = A::getInstance();
        ptr1 -> started = true; // check here if A had been started already !!!!
        return (ptr1);
    }

    static void end()
    {
        A* ptr1 = A::getInstance();
        ptr1 -> started = false; // check here if A had ever been started !!!!
        //A::deleteInstance();      // may be it will be useful here
    }
  private:
    bool started = false;
    static A *instance_;
    A() {};
    ~A() {};
};

int main()
{
  A *someVar = NULL;
  someVar = aSingletonClass::getInstance();
  A::deleteInstance();

  return 0;
}
person Eir Nym    schedule 15.12.2010

Ваша вторая версия не является одноэлементной, потому что у вас нет статического указателя A* и вы просто возвращаете новый каждый раз, когда вызывается start(), поэтому в вашем коде допустимо следующее:

int main()
{
    A* ptr = A::start();
    A* ptr2 = A::start();
    A* ptr3 = A::start();
    // etc
    ptr->end();
    ptr2->end();
    ptr3->end();
    return 0;
}; // eo main
person Moo-Juice    schedule 15.12.2010

Фу. Нехороший способ делать синглтоны!

Я бы сделал что-то вроде следующего..

class A
{
private:
  A() {}

public:

  static A& instance()
  {
    static A _inst;
    return _inst;
  }

};

Использовать,

A& inst = A::instance()

Всегда будет возвращать единственный экземпляр!

РЕДАКТИРОВАТЬ: у этого подхода есть несколько преимуществ - вам не нужно беспокоиться об очистке, но он лениво загружается (или инициализируется), и вы работаете со ссылками! Черт возьми, вы могли бы даже иметь постоянный синглтон (почему, я уверен, что вы можете придумать какое-то применение! ;))

person Nim    schedule 15.12.2010
comment
Привет, Ним. Как насчет этого кода. Я взял идею из твоего ответа (какая-то разница или влияние??) - person user436212; 17.12.2010
comment
Но здесь есть проблема. Предположим, есть другой запрос A& inst2 = A::instance() ... В этом случае я получу ссылку, которая должна была быть ограничена. !! inst и inst2 теперь работают над одним и тем же объектом одновременно, что может вызвать ошибку. Насколько я понимаю, только когда один удаляет экземпляр, другой должен получить ссылку. - person user436212; 17.12.2010
comment
Весь смысл синглтона в том, что к одному экземпляру можно получить доступ во многих местах. Я не понимаю, что вы имеете в виду во втором пункте (или о чем вы спрашиваете в своем первом пункте). Если у вас есть многопоточный доступ к синглтону, вы должны убедиться, что вы заблокировали все соответствующие методы. Если вам нужно удалить предыдущий экземпляр перед следующим доступом, я не думаю, что вам нужен шаблон singleton! Вам серьезно нужно пересмотреть свой дизайн! - person Nim; 18.12.2010

Код 2 не будет синглтоном. В функции start() вы возвращаете указатель на новый объект A. Но в функции end() вы удаляете этот объект. Таким образом, это не сработает.

person Sigel    schedule 15.12.2010