Достижение C # «только для чтения» поведения в C ++ - PullRequest
1 голос
/ 05 июня 2010

это мой первый вопрос о переполнении стека, так что будьте осторожны.

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

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

Мой подход к реализации моей цели состоит в том, чтобы использовать extern для объявления глобальной ссылки на одну тонну (которую я позже опишу в момент, когда я выберу. То, что я имею, выглядит примерно так,

namespace Global
{
    extern Singleton& mainInstance; // not defined yet, but it will be later!
}

int main()
{
    // now that the program has started, go ahead and create the singleton object
    Singleton& Global::mainInstance = Singleton::GetInstance(); // invalid use of qualified name
    Global::mainInstance = Singleton::GetInstance(); // doesn't work either :( 
}

class Singleton
{
    /* Some details ommited */

    public:
        Singleton& GetInstance()
        {
            static Singleton instance; // exists once for the whole program
            return instance;
        }
}

Однако на самом деле это не работает, и я не знаю, куда идти.

Некоторые подробности о том, с чем я столкнулся:

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

Представьте себе, если Процесс A создает Процесс B, где B содержит несколько синглетонов, распределенных по нескольким файлам и / или библиотекам. Это может быть настоящим кошмаром, если я не могу надежно обеспечить порядок создания экземпляров этих одноэлементных объектов (поскольку они могут зависеть друг от друга, а вызов методов для объекта NULL, как правило, является плохой вещью).

Если бы я был в C #, я бы просто использовал ключевое слово readonly, но есть ли способ реализовать это (поддерживается компилятор) поведение в C ++? Это даже хорошая идея? Спасибо за любой отзыв.


Редактировать

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

class EntryPoint
{

    /* Intentionally defined this way to discourage creation */
    EntryPoint(const EntryPoint &); // undefined & private
    EntryPoint& operator=(const EntryPoint &); // undefined & private

    // public
    EntryPoint()
    {
        /* All of the action is performed here! */
    }

    /* Other supporting functions */
}

// The easier to understand main function!
int main()
{
    EntryPoint * ep = new EntryPoint(); // transfer control to the entrypoint
    delete ep;
}

Одна из причин, по которой я думал, что мне понадобятся все эти синглтоны, заключается в том, что я планирую создать более крупную архитектуру, которая будет поддерживать модульные приложения типа плагина. Я также хотел больше проверки ошибок и защиты памяти, чтобы минимизировать утечки памяти. Я был рад обнаружить, что кроссплатформенный Qt (http://qt.nokia.com/) предлагает защищенный указатель и другие интересные функции.

Ответы [ 2 ]

1 голос
/ 05 июня 2010

Разрешить доступ только по телефону:

Singleton::GetInstance 

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

private:
   Singleton(){}
   Singleton(Singleton const&){}; //copy ctor private
   Singleton& operator=(Singleton const&){}; 
1 голос
/ 05 июня 2010

Почему бы просто не использовать Singleton::GetInstance напрямую? Почему вы должны хранить его в глобальном (только для чтения)? Это также решает проблемы с зависимостями.

...