- •Раздел 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.3.3. Составные типы данных. Структуры
Массив, как известно, объединяет под одним именем переменные (элементы) одинакового типа. Структуры служат для объединения в одной переменной элементов разных типов. Например, нижеследующая структура Man объединяет элементы типов int и char*:
struct Man // Структура как тип данных для учета людей
{
int Age; // Возраст
char *Name; //Имя
}
Идентификатор Man именует только тип структуры (structure tag), то есть определяет новый тип данных, используемый в программе. Чтобы иметь возможность работы с реальной структурой, надо создать представитель типа (instance of a struct), то есть определить переменную типа Man. В языке C++ для этого достаточно сделать объявление Man m;. Теперь можно работать с переменной m как со структурой. Добраться до элемента структуры можно с помощью операции <точка>. Например, оператор m.Age=49: присваивает элементу Age структуры m типа Man значение 49.
Следующий фрагмент иллюстрирует достаточно надежный способ ввода с консоли значения текстовой строки (в данном случае элемента Name структуры т):
unsigned n; //Длина имени
char buf[80], *p; //Буфер ввода и указатель на начало строки
buf[0] = 60; // Ограничение на длину строки
р = cgets(buf); //Ввод в буфер
n = buf[l]; // Количество фактически введенных символов
if (n) // Если что-нибудь введено
{
m.Name = new char[n+l]; // Захват памяти
strcpy(m.Name.p); // Копирование строки
}
Непосредственный ввод в буфер (обычно многократно используемый для ввода различных строк текста) осуществляет функция cgets. Все остальные операторы обеспечивают надежность. Правила игры задает функция cgets. Она требует, чтобы предварительно в buf [0] было задано максимально допустимое количество символов в строке. Она помещает в buf[l] количество фактически введенных символов и возвращает указатель на начало строки. Сама строка размещается, начиная с buf[2], поэтому cgets присваивает переменной р адрес buf[2]. Далее в фрагменте выполняются следующие действия. Если количество введенных символов строки не равно нулю, то она копируется из буфера в предварительно отведенную для нее область памяти. Надежность ввода обеспечивается тем, что пользователь может нажимать любое количество любых клавиш (по одной), и при этом программа не будет вести себя непредсказуемым образом.
Структуры значительно облегчают процесс обмена данными между функциями. Если требуется передать в функцию большое количество разнородных по типу (но не по смыслу) данных, то длинный список аргументов, во-первых, делает программу нечитабельной, во-вторых, увеличивает время на обработку заголовка функции и перегружает стек. Значительно проще передать ссылкой или адресом одну структуру, объединяющую разнородные данные.
Элементами структуры могут также быть структуры другого типа или указатели на структуру того же типа.
Частным, особым случаем структуры являются union-структуры. union — это структура, все элементы которой имеют нулевое смещение. Они требуют столько памяти, сколько занимает самый большой ее элемент. Указанный тип структур выравнивается так, чтобы можно было работать с любым элементом. В языке C++ появляется возможность декларации анонимной union-структуры, то есть структуры без имени, например:
struct Captain // Тип объемлющей структуры
{
char *name, *ship; //Два ее элемента
int river; // Третий элемент, задающий способ
// интерпретации четвертого элемента
union
{ // четвертый элемент: union-структура
long on_sea_hours; // Различные интерпретации
short years_of_service; // одной и той же области памяти
}
В каждый момент времени union хранит в отведенной для него компилятором области памяти только один из двух типов значений (long или short):
• если long, тогда его надо интерпретировать как on_sea_hours;
• если short, тогда это значение переменной years_of service.
Получить доступ к элементу анонимной union-структуры можно следующим образом:
Captain cap; // Объявление структуры типа Captain
// Инициализация полей структуры и другие действия
if (cap.river) // Анализ способа интерпретации
printf ("River service: %d years",cap.years_of_service): // Одна интерпретация union
else
printf ("Hours on sea: %1 hrs", cap. on_sea_hours): // Другая интерпретация
Указатель на какую-либо структуру может быть объявлен внутри другой структуры до того, как первая структура была декларирована. Например:
struct А; //Незавершенная декларация или упреждающее объявление
struct В { struct A *pa };
struct А { struct В *pb };
Объявление struct А; является неполным (incomplete), так как структура А не определена в точке объявления. Ниже появляется полная декларация структуры А, которая содержит указатель на уже определенную структуру В. Неполная декларация struct А допустима потому, что определение struct В не требует знания размера struct A.