Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ТП лекции Раздел 4.doc
Скачиваний:
16
Добавлен:
28.09.2019
Размер:
2.56 Mб
Скачать

4.7.3. Статические члены классов.

Как к данным, так и к методам класса может быть применен спецификатор клас­са памяти static. Выше было отмечено, что каждый объект класса имеет свои собственные копии всех элементов из списка данных класса. Однако элемент данных, имеющий описатель static, существует только в одном экземпляре и используется всеми объектами рассматриваемого класса. К этому элементу мож­но обращаться без указания имени объекта. Необходимо лишь явно указать класс, в котором элемент объявлен. Таким образом, объект класса может быть еще не создан, а обращение к элементу, общему для всех объектов класса, уже возмож­но. Рассмотрим пример:

#define P printf("\n%d objects of %s",A::GetCount(),A::Name)

// Директива препроцессора, в тексте P заменяется на строку

class A

{ private:

static int Mum; // Число объектов класса А — static-переменная

publiс:

int i; // Доступная переменная

static char* Name; // Статическая переменная

static int GetCount() //Статические функции класса

{ return Num; }

static void Set(A& obj, int j) { obj.i=j; }

А(){ Num++; } // Конструктор увеличивает количество объектов ~А() { Num--; Р; } //Деструктор — уменьшает

};

int A::Num = 0; //Доступ без помощи объекта класса

char* A::Name;

void main ()

{

A::Name = "Class A";

P;

A a; // Создание в стеке

Р; А *ра = new А; // Создание в heap

Р; delete pa; // Освобождение heap A arr[5]; //Массив объектов

P;

//Доступ с помощью объекта класса char buff[] = "New class Name"; a.Name = strcpy(new char[strlen(buff)+l],buff): A::Set(a.7); printf(“\n i=%d”,a.i); arr[3].Set(a,8); printf("\n i=%d",a.i);

}

Объявление static int Num: внутри класса А объявляет (declares), но не опре­деляет (defines) переменную. Определение static-переменных необходимо вы­полнять глобально. Оператор int A::Num=0; делает это вне функции main и явно инициализирует переменную Num. Вторая переменная, будучи глобальной, инициализируется нулем неявно. Так как класс декларирован глобально, то не­возможны локальное определение и инициализация переменных. Компилятор даст сообщение об ошибке, если перенести определение int A::Num = 0; внутрь main. Так как статические переменные не привязаны ни к какому объекту клас­са, то объекты а, *ра и аrr[] класса А пользуются общими экземплярами пере­менных Name, Num. Заметьте, что конструктор вызывается при создании всех объек­тов и увеличивает счетчик созданных объектов на единицу. Так как переменная Num является скрытой (private), то пользователь не в состоянии ошибочными действиями исказить текущее реальное количество объектов класса. Но он мо­жет повлиять на значение другой (public) static-переменной Name. Сделать это можно как в применении к объекту класса (а. Name = ...), так и без какой-либо привязки к объекту (A::Name = ...). В обоих случаях будет изменена одна и та же общая переменная Name.

Теперь рассмотрим особенности функционирования статических функций — членов класса. Так как static-метод может быть вызван безотносительно к како­му-либо объекту класса, то при его вызове не происходит неявной передачи ука­зателя this. Вспомните, указатель this всегда неявно передается обычному (не static) методу. Следовательно, внутри статического метода невозможно прямое обращение к остальным (не статическим) членам этого же класса, так как неиз­вестно, какому представителю класса (объекту) должны принадлежать эти чле­ны. Выходом из этого положения служит явная передача ссылки или адреса объек­та, для которого вызывается статическая функция. Так мы поступили при вызове А:: Set (а, 7);. Только потому, что ссылка на объект а была передана статической функции в качестве параметра, она может работать с полем int i конкретного объекта. Традиционный вызов arr[3].Set(a,8); также допустим для static-функ­ции, но и в этом случае не обойтись без параметра, так как для статической функции указатель this не передается неявным образом, как это делается при вызове обычных методов класса.

Обычно static-члены класса используются для управ­ления данными, общими для всех объектов класса. Например, чтобы вести под­счет количества уже созданных объектов класса или следить за именем последнего использованного ресурса, разделяемого всеми объектами.