это - мой первый вопрос на переполнении стека, так быть нежным.
Позвольте мне сначала объяснить точное поведение, которое я хотел бы видеть. Если Вы знакомы с C# затем, Вы знаете, что объявление переменной как "только для чтения" позволяет программисту присваивать некоторое значение той переменной точно однажды. Дальнейшие попытки изменить переменную приведут к ошибке.
Что я после: Я хочу удостовериться, что любой и все singleton-классы, которые я определяю, можно очевидно инстанцировать точно однажды в моей программе (больше деталей внизу).
Мой подход к пониманию моей цели должен использовать экстерна для объявления глобальной ссылки на одиночный элемент (которого я позже инстанцирую за один раз, я выбираю. То, из чего у меня есть вид, похоже на это,
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;
}
}
Однако это действительно не работает, и я не знаю, куда пойти отсюда.
Некоторые детали о том, против чего я противостою:
Я обеспокоен поточной обработкой, поскольку я работаю над кодом, который будет иметь дело с игровой логикой при общении с несколькими сторонними процессами и другими процессами, которые я создам. В конечном счете я должен был бы реализовать некоторую синхронизацию, таким образом, несколько потоков могли получить доступ к информации в Singleton-классе без беспокойства. Поскольку я не знаю, какие виды оптимизации я хотел бы делать, или точно что влечет за собой поточная обработка (никогда не делавшийся реальный проект с помощью него), я думал, что способность очевидно управлять, когда Одиночные элементы инстанцировали, будет Хорошей Вещью.
Вообразите, создает ли Процесс A Процесс B, где B содержит несколько Одиночных элементов, распределенных против нескольких файлов и/или библиотек. Это мог быть реальный кошмар, если я не могу надежно гарантировать порядок, эти одноэлементные объекты инстанцируют (потому что они могли зависеть друг от друга, и вызывающие методы для Несуществующего объекта обычно являются Плохой Вещью).
Если бы я был в C#, то я просто использовал бы ключевое слово только для чтения, но был бы там каким-либо способом, которым я могу реализовать это (поддерживаемый компилятор) поведение в 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/) предлагает защищенный указатель и другие замечательные функции.
Почему бы просто не использовать Singleton::GetInstance
напрямую? Зачем хранить его в (доступном для чтения) глобале? Это также решает проблему зависимостей.
Разрешить доступ только по телефону:
Singleton::GetInstance
Обеспечьте это, сделав ваши конструкторы копирования и присваивания закрытыми
private:
Singleton(){}
Singleton(Singleton const&){}; //copy ctor private
Singleton& operator=(Singleton const&){};