Конечно, есть исключения. Лично я не могу вспомнить ни одной ситуации, когда goto - это правильное решение (или где singleton - правильное решение), но глобальные переменные иногда имеют свое применение. Но ... вы не нашли веского оправдания.
Большинство объектов в вашей игре не , повторяю, не требуется для доступа к экранному буферу. Это ответственность рендерера и никого больше. Вы не хотите, чтобы ваш логгер, менеджер ввода, ИИ или кто-то еще выводил на экран случайный мусор.
И именно поэтому люди говорят "не используйте глобалы". Это не потому, что глобалы - это какое-то абсолютное зло, а потому, что если мы не скажем это, люди попадут в ловушку, в которой вы находитесь, "да, но это правило не относится к me , верно? Мне нужно все, чтобы иметь доступ к X ". Нет, вам нужно научиться структурировать вашу программу.
Более распространенные исключения - для объектов без состояния или статических, таких как регистратор или, возможно, конфигурация вашего приложения: вещи, которые доступны только для чтения или только для записи и которые действительно должны быть доступны из везде . В каждой строке кода может потребоваться написать сообщение журнала. Таким образом, регистратор является честным кандидатом на то, чтобы стать глобальным. Но 99% вашего кода даже не должны знать, что экранный буфер существует .
Проблема глобалов заключается в том, что они нарушают инкапсуляцию:
Код, который зависит от глобального, менее пригоден для повторного использования. Я могу взять тот же класс, который вы используете, поместить его в мое приложение, и он сломается. Потому что у меня нет той же сети глобальных объектов, от которой она зависит.
Это также делает код сложнее рассуждать. Какое значение вернет функция f(x)
?
Очевидно, это зависит от того, что x
. Но если я дважды пройду один и тот же x
, получу ли я такой же результат? Если он использует много глобалов, то, вероятно, нет. Тогда становится действительно трудно просто понять, что он собирается вернуть, а также то, что еще он собирается сделать. Будет ли она устанавливать какую-то глобальную переменную, которая будет влиять на другие, казалось бы, не связанные функции?
Как этого достичь, желательно без необходимости передавать его каждому конструктору для внутреннего хранения до необходимости
Ты говоришь так, будто это плохо. Если объект должен знать о экранном буфере, то вы должны дать ему экранный буфер. Либо в конструкторе, либо в более позднем вызове. (И у него есть приятный бонус: он предупреждает вас , если ваш дизайн неаккуратный. Если у вас есть 500 классов, которым нужно использовать экранный буфер, тогда вы должны передать его 500 конструкторам. Это больно, и так что это будильник: Я делаю что-то не так. Многим объектам не нужно знать о экранном буфере. Как я могу это исправить? `)
В качестве более очевидного примера, скажем, я хочу вычислить косинус 1.42, поэтому я передаю 1.42 функции: cos(1.42)
Вот как мы обычно это делаем, без глобалов. Конечно, мы могли бы вместо этого сказать: «Да, но каждый должен иметь возможность установить аргумент на cos
, я бы лучше сделал его глобальным». Тогда это будет выглядеть так:
gVal = 1.42;
cos();
Я не знаю о вас, но я думаю, что первая версия была более читабельной.