как реализовать синглтон в C ++ - PullRequest
0 голосов
/ 21 ноября 2011

Этот пост - это то, что я только что прочитал.

То, как он реализует Singleton в C ++, сбивает меня с толку.У меня есть несколько вопросов об этом, и вот его код:

template<typename T>
class Singleton {
public:
    static T& getInstance() {  //Question 1
        return instance;
    }
private:
    static T instance;
};

class DebugLog : public Singleton<DebugLog> {  //Question 2
public:
    void doNothing() {}
};

Вопрос

  1. Я думаю, мы должны поставить static T& getInstance() 'Определение вне тела класса, верно?

  2. Он пытается сделать class DebugLog одноэлементным классом, но когда он наследует Singleton<DebugLog>, DebugLog еще не существует, право?Если правильно, то как класс шаблона Singleton может создать экземпляр несуществующего класса?

Ответы [ 3 ]

5 голосов
/ 21 ноября 2011

1) Нет, неважно, как вы структурируете свой код.Кстати, Singleton - это не класс: это шаблон .Так как полное определение шаблона в любом случае должно быть доступно на любом сайте создания экземпляра, вы можете также определить все встроенное.

2) class DebugLog : public Singleton<DebugLog> хорошо.Мы не наследуем от несуществующего класса;скорее мы наследуем от класса Singleton<DebugLog>.Шаблоны могут быть созданы на неполных типах.(Есть несколько правил, которые вы можете и не можете делать с таким параметром типа.)

Например, template <typename T> class Foo { };, безусловно, может быть создан для любого типа без проблем.Что еще интереснее, template <typename T> struct PointerFactory { typedef T * type; }; может быть создан для любого типа, полный или нет.В данной ситуации цель параметра шаблона в CRTP состоит исключительно в информировании базового класса о его возможном производном типе, так что это вполне нормально.

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

Стандарт C ++ не говорит о «существовании» в отношении классов (или чего-либо еще).В момент создания шаблона поиск имени находит DebugLog и обнаруживает, что это класс (то есть тип).В этот момент это неполный тип, и есть только ограниченные возможности, которые вы можете сделать с неполным типом.Если шаблон класса, который создается, не делает ничего, что требует полного типа (а Singleton не делает), тогда проблем нет.(Обратите внимание, что на этом этапе создается только определение класса; функции-члены класса не будут создаваться до тех пор, пока они не будут использованы.)

Могу добавить, что в опубликованном вами коде все еще отсутствует одна важная вещь:нет определения для объявления Singleton::instance.Вам все еще нужно добавить:

template<typename T> T Singleton<T>::instance;

где-нибудь.

0 голосов
/ 21 ноября 2011

Вы должны использовать указатель на T в этом случае:

template<typename T>
class Singleton {
public:
    static T& getInstance() {
        static T * instance = NULL;
        if (!instance)
            instance = new T;
        return *instance;
    }
};

class DebugLog : public Singleton<DebugLog> {  //Question 2
    public:
        void doNothing() {}
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...