Иногда необходимо, чтобы к одной переменной можно было обращаться из разных функций. Предположим, в нашей программе используется генератор случайных чисел. Мы хотим инициализировать его один раз, в начале выполнения программы, а затем обращаться к нему из разных частей программы. Рассмотрим несколько возможных реализаций.
Во-первых, определим класс RandomGenerator с двумя методами: Init, для инициализации генератора, и GetNumber — для получения следующего числа.
//// файл RandomGenerator.h//class RandomGenerator{public: RandomGenerator(); ~RandomGenerator(); void Init(unsigned long start); unsigned long GetNumber();private: unsigned long previousNumber;};//// файл RandomGenerator.cpp//#include "RandomGenerator.h"#include <time.h>voidRandomGenerator::Init(unsigned long x){ previousNumber = x;}unsigned longRandomGenerator::GetNumber(void){ unsigned long ltime; // получить текущее время в секундах, // прошедших с полуночи 1 января 1970 года time(<ime); ltime <<= 16; ltime >>= 16; // взять младшие 16 битов previousNumber = previousNumber * ltime; return previousNumber;}
Первый вариант состоит в создании объекта класса RandomGenerator в функции main и передаче ссылки на него во все функции и методы, где он потребуется.
Поскольку функция main завершает работу программы, все необходимые условия выполнены: генератор случайных чисел создается в самом начале программы, все объекты и функции обращаются к одному и тому же генератору, и генератор уничтожается по завершении программы. Такой стиль программирования допустимо использовать только в том случае, если передавать ссылку на используемый экземпляр объекта требуется нечасто. В противном случае этот способ крайне неудобен. Передавать ссылку на один и тот же объект утомительно, к тому же это загромождает интерфейс классов.
Язык Си++ предоставляет возможность определения глобальной переменной. Если переменная определена вне функции, она создается в самом начале выполнения программы (еще до начала выполнения main). Эта переменная доступна во всех функциях того файла, где она определена. Аналогично прототипу функции, имя глобальной переменной можно объявить в других файлах и тем самым предоставить возможность обращаться к ней и в других файлах:
// файл main.cpp#include "RandomGenerator.h"// определение глобальной переменной RandomGenerator rgen;main(){ rgen.Init(1000);}voidfun1(void){ unsigned long x = rgen.GetNumber(); . . . }// файл class.cpp #include "RandomGenerator.h"// объявление глобальной переменной, // внешней по отношению к данному файлу extern RandomGenerator rgen;Class1::Class1(){ . . .}voidfun2(){ unsigned long x = rgen.GetNumber(); . . . }
Объявление внешней переменной можно поместить в файл-заголовок. Тогда не нужно будет повторять объявление переменной с описателем extern в каждом файле, который ее использует.
Модификацией определения глобальной переменной является добавление описателя static. Для глобальной переменной описатель static означает то, что эта переменная доступна только в одном файле – в том, в котором она определена. (Правда, в данном примере такая модификация недопустима – нам-то как раз нужно, чтобы к глобальной переменной rgen можно было обращаться из разных файлов.)