c ++ Майерс синглтон неопределенная ссылка - PullRequest
0 голосов
/ 26 января 2011

У меня есть следующий код, который реализует базовый синглет Мейерса:

#ifndef _cConfigFile_HH
#define _cConfigFile_HH

class cConfigFile {
public:
  static cConfigFile& getInstance() {
    static cConfigFile instance;
    return instance;
  };
private:
  cConfigFile();
};

#endif

Мой компилятор не позволяет мне скомпилировать это, выдав следующую ошибку:

/include/cConfigFile.hh:7: undefined reference to `cConfigFile::cConfigFile()'

ошибка, которую я понимаю, что мне нужно объявить «instance» в файле .cpp, но я не могу объявить cConfigFile :: instance, потому что компилятор говорит:статический

Что я делаю не так ??Я здесь потерян ..

Ответы [ 4 ]

10 голосов
/ 26 января 2011

Вы забыли реализовать свой конструктор.

0 голосов
/ 26 января 2011

Это не совсем ответ, просто ответ на комментарий, который слишком длинный для другого комментария, и он имеет отношение к этому вопросу.

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

Это причина (хотя, ИМХО, не обязательноотличный вариант) для глобальной переменной, но не причина для синглтона.Какой вред существует в более чем одном объекте, который хранит существующую конфигурацию?Если бы все пользователи использовали глобальную переменную для доступа к ней, они все использовали бы одну и ту же.Почему полезно принудительно ограничивать количество экземпляров до одного?

Во-вторых, что произойдет в будущем, когда вам потребуется временно добавить некоторые параметры конфигурации?Скажем, каким-то образом ваша программа должна быть запущена как подпрограмма или что-то с немного другой информацией о конфигурации, а затем восстановить исходную конфигурацию?Или, может быть, вам нужно несколько раз изменить конфигурацию для тестирования, а затем восстановить ее в исходное состояние?С Singleton и глобальной переменной это становится очень сложно.Но если вы использовали что-то более гибкое, это довольно тривиально.

Теперь лично я думаю, что передача параметров конфигурации всем вещам, которые нуждаются в них явным образом, не обязательно является плохим способом.Но если вы считаете, что это недопустимо, вот альтернатива:

template <typename T>
class DynamicallyScoped {
 public:
   explicit DynamicallyScoped(T &stackinstance) : oldinstance_(0) {
      oldinstance_ = S_curinstance;
      S_curinstance = &stackinstance;
   }
   ~DynamicallyScoped() {
      S_curinstance = oldinstance_;
      oldinstance_ = 0;
   }
   static T *curInstance() { return S_curinstance; }

 private:
   static T *S_curinstance;
   T *oldinstance_;

   // Made private and left undefined on purpose.
   DynamicallyScoped(const DynamicallyScoped &b);
   const DynamicallyScoped &operator =(const DynamicallyScoped &b);
};

Это позволяет вам заменить текущий экземпляр для области и автоматически восстановить его, когда эта область исчезнет.И это также позволяет вам говорить DynamicallyScoped<Foo>::curInstance()->get_something(); в любом месте вашей программы, кроме конструкторов для статических или глобальных объектов, и ожидать получить что-то полезное.

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

Пример использования:

#include <iostream>

template <>
int *DynamicallyScoped<int>::S_curinstance = 0;

extern void doSomething();
extern void doSomethingElse();
extern void printTheInt();

int main(int argc, char *argv[])
{
    int x = 5;
    DynamicallyScoped<int> theInt(x);

    printTheInt();
    doSomething();
    doSomethingElse();
}

void doSomething()
{
    printTheInt();
}

void doSomethingElse()
{
    int newint = 6;
    DynamicallyScoped<int> subint(newint);
    doSomething();
}

void printTheInt()
{
    ::std::cout << "_The_ integer's value is: "
                << *DynamicallyScoped<int>::curInstance() << '\n';
}

Что касается беспокойства о том, что больше экземпляров вашего "глобального файла конфигурации"объект может быть создан, не жестко закодируйте имя файла.Создайте объект в main как переменную стека и дайте ему имя файла в качестве аргумента.Тогда не будет проблем, если другие части кода создадут экземпляры объекта файла конфигурации, если они также не дадут имя файла глобальной конфигурации.И если они это делают, они заслуживают того, что получают.

0 голосов
/ 26 января 2011

Первое сообщение об ошибке означает, что вы пропустили конструктор для экземпляра.

Что касается второго: было бы неплохо включить код .cpp, в котором вы пытались определить экземпляр,Но звучит так, будто вы пытались определить переменную экземпляра как статический класс, чего вы не должны делать.

Чтобы создать экземпляр экземпляра в .cpp, вы хотите иметь что-то подобное в своем.hh file:

class cConfigFile {
public:
  static cConfigFile& getInstance();
private:
  cConfigFile() {} // Note: define the constructor -- this is probably not enough!
};

И это в вашем .cpp файле:

cConfigFile& cConfigFile::getInstance()
{
    // Define the singleton as a local static
    static cConfigFile instance;

    return instance;
}

NOTE : Вы действительно хотите определить *Метод 1015 * в файле .cpp, а не встроенная функция.Определение его как встроенного даст вам один экземпляр instance для каждого файла .cpp, в котором используется заголовок.Это побеждает цель сделать его одиноким!

0 голосов
/ 26 января 2011

Вам нужно инициализировать статический экземпляр внизу файла заголовка:

cConfigFile cConfigFile :: instance;

И вам нужно взять объявление статического экземпляра вне функции getInstance ().

class cConfigFile{
public:
  static cConfigFile instance;   //declare

  cConfigFile & getInstance(){

    return instance;
  }
private:
  cConfigFile(){}
};

cConfigFile cConfigFile::instance();  //initialize
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...