- •Раздел 4. Разработка по Тема 4.1. Проектирование интерфейса с пользователем
- •4.1.1. Типы пользовательских интерфейсов.
- •4.1.2. Пользовательская и программная модели интерфейса.
- •4.1.3. Разработка диалогов.
- •4.1.4. Основные компоненты графических пользовательских интерфейсов.
- •Тема 4.2. Реализация графических пользовательских интерфейсов.
- •4.2.1. Диалоги, управляемые пользователем.
- •4.2.2. Диалоги, управляемые системой.
- •4.2.3. Использование метафор.
- •4.2.4. Технология Drag and Drop.
- •4.2.5. Интеллектуальные элементы.
- •4.3.1. Базовые типы данных.
- •Константы
- •Область действия имен
- •4.3.2. Указатели и адресная арифметика.
- •4.3.3. Составные типы данных. Структуры
- •Битовые поля
- •Определение типов
- •Перечислимые типы
- •4.3.4. Выражения и операции.
- •4.3.5. Управляющие конструкции. Условные операторы
- •Операторы циклов
- •4.4.1. Статические одномерные массивы.
- •4.4.2. Статические многомерные массивы.
- •4.4.3. Динамические массивы.
- •4.4.4. Массивы указателей.
- •4.5.1. Стеки.
- •4.5.2. Очереди.
- •4.5.3. Списки.
- •4.5.4. Бинарные деревья.
- •4.6.1. Объявление классов и экземпляров классов.
- •4.6.2. Инкапсуляция данных и методов.
- •4.6.3. Конструкторы классов.
- •Конструктор по умолчанию
- •Конструктор копирования
- •4.6.4. Деструкторы классов.
- •4.7.1. Разделы в описании класса.
- •4.7.2. Friend-конструкции.
- •4.7.3. Статические члены классов.
- •4.7.4. Использование описателя const в классах.
- •4.8.1. Вложенность классов.
- •4.8.2. Наследование данных и методов.
- •4.8.3. Типы наследования.
- •4.9.1. Полиморфизм раннего связывания.
- •4.9.2. Полиморфизм позднего связывания и виртуальные функции.
- •4.9.3. Абстрактные методы и классы.
- •4.10.1. Функции консольного ввода-вывода.
- •4.10.2. Функции файлового ввода-вывода.
- •4.10.3. Использование библиотеки классов потокового ввода-вывода.
- •4.11.1. Перегрузка операций.
- •4.11.2. Шаблоны функций.
- •4.11.3. Шаблоны классов.
- •4.11.4. Обработка исключений.
- •Тема 4.12. Com-технология.
- •4.12.1. Основные понятия.
- •4.12.2. Типы интерфейсов.
- •Свойства интерфейсов
- •Типы интерфейсов
- •4.12.3. Типы com-объектов.
- •4.12.4. Фабрика классов.
- •Тема 4.13. Построение com-сервера.
- •4.13.1. Язык idl.
- •Содержимое файла idl
- •4.13.2. Определение пользовательского интерфейса.
- •4.13.3. Реализация пользовательского интерфейса.
- •4.13.4. Создание тестового клиента.
- •Тема 4.14. Обзор платформы ms .Net.
- •4.14.1. Общая идея архитектуры .Net.
- •4.14.2. Достоинства и недостатки .Net.
- •4.14.3. Схема трансляции программ в .Net.
- •4.14.4. Язык msil.
- •4.14.5. Объектно-ориентированная модель .Net.
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-члены класса используются для управления данными, общими для всех объектов класса. Например, чтобы вести подсчет количества уже созданных объектов класса или следить за именем последнего использованного ресурса, разделяемого всеми объектами.