это мой первый вопрос о переполнении стека, так что будьте осторожны.
Позвольте мне сначала объяснить точное поведение, которое я хотел бы видеть. Если вы знакомы с 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/) предлагает защищенный указатель и другие интересные функции.