Глобальный экземпляр класса в C ++ - PullRequest
9 голосов
/ 18 ноября 2008

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

Ответы [ 7 ]

18 голосов
/ 18 ноября 2008

Все усилия по созданию одноэлементного объекта с использованием обычного шаблона не решают вторую часть вашего вопроса - способность зарабатывать больше при необходимости. Одноэлементный «шаблон» очень ограничен и является не чем иным, как глобальной переменной с другим именем.

// myclass.h

class MyClass {
public:
    MyClass();
    void foo();
    // ...
};

extern MyClass g_MyClassInstance;

// myclass.cpp

MyClass g_MyClassInstance;

MyClass::MyClass()
{
    // ...
}

Теперь, в любом другом модуле просто включите myclass.h и используйте g_MyClassInstance как обычно. Если вам нужно сделать больше, есть готовый конструктор для вызова.

3 голосов
/ 18 ноября 2008

Прежде всего тот факт, что вам нужны глобальные переменные, - это «запах кода» (по словам Мартина Фаулера).

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

class MyVar
{
    public:
        static MyVar& getGlobal1()
        {
            static MyVar  global1;
            return global1;
        }
        static MyVar& getGlobal2()
        {
            static MyVar  global2;
            return global2;
        }
        // .. etc
}
1 голос
/ 18 ноября 2008

В качестве небольшого изменения в шаблоне синглтона, если вы хотите разрешить возможность создания большего количества экземпляров с различным временем жизни, просто сделайте ctors, dtor и operator = public. Таким образом, вы получаете один глобальный экземпляр через GetInstance, но вы также можете объявить другие переменные в куче или стеке того же типа.

Однако основная идея - шаблон синглтона.

0 голосов
/ 18 ноября 2008

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

Мой поворот заключается в том, что я редко использую статическую функцию-член, если я не хочу создать настоящий синглтон и скрыть constr. Мой обычный подход таков:

template< typename T >
T& singleton( void )
{
   static char buffer[sizeof(T)];
   static T* single = new(buffer)T;
   return *single;
}

Foo& instance = singleton<Foo>();

Почему бы не использовать статический экземпляр T вместо размещения new? Статический экземпляр дает гарантии порядка строительства, но не порядок уничтожения. Большинство объектов уничтожаются в обратном порядке построения, но статические и глобальные переменные. Если вы используете статическую версию экземпляра, вы в конечном итоге получите загадочные / прерывистые ошибки сегмента и т. Д. После окончания main.

Это означает, что деструктор синглетонов никогда не будет вызван. Тем не менее, процесс в любом случае идет вниз, и ресурсы будут восстановлены. К этому сложно привыкнуть, но, поверьте мне, на данный момент нет лучшего кроссплатформенного решения. К счастью, в C ++ 0x внесены изменения, чтобы гарантировать порядок уничтожения, который решит эту проблему. Как только ваш компилятор поддерживает новый стандарт, просто обновите функцию singleton, чтобы использовать статический экземпляр.

Кроме того, я в реальной реализации использую boost, чтобы получить выровненную память вместо простого символьного массива, но не хотел усложнять пример

0 голосов
/ 18 ноября 2008

Singleton - хороший шаблон для использования, но у него есть свои недостатки. Прочитайте следующие блоги Miško Hevery перед использованием синглетонов.

  1. Синглетоны - патологические лжецы

  2. Первопричина синглетонов

  3. Куда пропали все синглтоны?

0 голосов
/ 18 ноября 2008

Самая простая и безопасная для параллелизма реализация - синглтон Скотта Мейера:


#include <iostream>

class MySingleton {
public:
    static MySingleton& Instance() {
        static MySingleton singleton;
        return singleton;
    }
    void HelloWorld() { std::cout << "Hello World!\n"; }
};

int main() {
    MySingleton::Instance().HelloWorld();
}

См. Тему IV здесь для анализа от Джона Влиссидеса (из известности GoF).

0 голосов
/ 18 ноября 2008

шаблон Singleton - это то, что вы ищете.

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