
- •1. Лекция: Начальные сведения о языке
- •2. Лекция: Имена, переменные и константы Имена
- •Переменные
- •Константы
- •3. Лекция: Операции и выражения Выражения
- •Операция присваивания
- •Арифметические операции
- •Операции сравнения
- •Порядок вычисления выражений
- •4. Лекция: Операторы Что такое оператор
- •Операторы-выражения
- •Объявления имен
- •Операторы управления
- •Условные операторы
- •Операторы цикла
- •Оператор возврата
- •Оператор перехода
- •5. Лекция: Функции Вызов функций
- •Имена функций
- •Необязательные аргументы функций
- •Рекурсия
- •6. Лекция: Встроенные типы данных Общая информация
- •Целые числа
- •Вещественные числа
- •Логические величины
- •Символы и байты
- •Кодировка, многобайтовые символы
- •Наборы перечисляемых значений
- •7. Лекция: Классы и объекты Понятие класса
- •Определение методов класса
- •Переопределение операций
- •Подписи методов и необязательные аргументы
- •Запись классов
- •8. Лекция: Производные типы данных Массивы
- •Структуры
- •Битовые поля
- •Объединения
- •Указатели
- •Адресная арифметика
- •Связь между массивами и указателями
- •Безтиповый (нетипизированный) указатель
- •Нулевой указатель
- •Строки и литералы
- •9. Лекция: Распределение памяти Автоматические переменные
- •Статические переменные
- •Динамическое выделение памяти
- •Выделение памяти под строки
- •Рекомендации по использованию указателей и динамического распределения памяти
- •Распределение памяти при передаче аргументов функции
- •Рекомендации по передаче аргументов
- •10. Лекция: Производные классы, наследование
- •Виртуальные методы
- •Виртуальные методы и переопределение методов
- •Преобразование базового и производного классов
- •Внутреннее и защищенное наследование
- •Абстрактные классы
- •Множественное наследование
- •Виртуальное наследование
- •11. Лекция: Контроль доступа к объекту Интерфейс и состояние объекта
- •Объявление friend
- •Использование описателя const
- •Доступ к объекту по чтению и записи
- •12. Лекция: Классы – конструкторы и деструкторы
- •Копирующий конструктор
- •Деструкторы
- •Инициализация объектов
- •Операции new и delete
- •13. Лекция: Дополнительные возможности классов Переопределение операций
- •Как определять операции
- •Преобразования типов
- •Явные преобразования типов
- •Стандартные преобразования типов
- •Преобразования указателей и ссылок
- •Преобразования типов, определенных в программе
- •14. Лекция: Компоновка программ, препроцессор Компоновка нескольких файлов в одну программу
- •Проблема использования общих функций и имен
- •Использование включаемых файлов
- •Препроцессор
- •Определение макросов
- •Условная компиляция
- •Дополнительные директивы препроцессора
- •15. Лекция: Определение, время жизни и области видимости переменных в больших программах Файлы и переменные
- •Общие данные
- •Глобальные переменные
- •Повышение надежности обращения к общим данным
- •Область видимости имен
- •Оператор определения контекста namespace
- •16. Лекция: Обработка ошибок Виды ошибок
- •Возвращаемое значение как признак ошибки
- •Исключительные ситуации
- •Обработка исключительных ситуаций
- •Примеры обработки исключительных ситуаций
- •17. Лекция: Ввод-вывод
- •Манипуляторы и форматирование ввода-вывода
- •Строковые потоки
- •Ввод-вывод файлов
- •18. Лекция: Шаблоны Назначение шаблонов
- •Функции-шаблоны
- •Шаблоны классов
- •"Интеллигентный указатель"
- •Задание свойств класса
Структуры
Структуры – это не что иное, как классы, у которых разрешен доступ ко всем их элементам (доступ к определенным атрибутам класса может быть ограничен, о чем мы узнаем в лекции 11). Пример структуры:
struct Record {
int number;
char name[20];
};
Так же, как и для классов, операция "." обозначает обращение к элементу структуры.
В отличие от классов, можно определить переменную-структуру без определения отдельного типа:
struct {
double x;
double y;
} coord;
Обратиться к атрибутам переменной coord можно coord.x и coord.y.
Битовые поля
В структуре можно определить размеры атрибута с точностью до бита. Традиционно структуры используются в системном программировании для описания регистров аппаратуры. В них каждый бит имеет свое значение. Не менее важной является возможность экономии памяти – ведь минимальный тип атрибута структуры это байт (char), который занимает 8 битов. До сих пор, несмотря на мегабайты и даже гигабайты оперативной памяти, используемые в современных компьютерах, существует немало задач, где каждый бит на счету.
Если после описания атрибута структуры поставить двоеточие и затем целое число, то это число задает количество битов, выделенных под данный атрибут структуры. Такие атрибуты называют битовыми полями. Следующая структура хранит в компактной форме дату и время дня с точностью до секунды.
struct TimeAndDate
{
unsigned hours :5; // часы от 0 до 24
unsigned mins :6; // минуты
unsigned secs :6; // секунды от 0 до 60
unsigned weekDay :3; // день недели
unsigned monthDay :6; // день месяца от 1 до 31
unsigned month :5; // месяц от 1 до 12
unsigned year :8; // год от 0 до 100
};
Одна структура TimeAndDate требует всего 39 битов, т.е. 5 байтов (один байт — 8 битов). Если бы мы использовали для каждого атрибута этой структуры тип char, нам бы потребовалось 7 байтов.
Объединения
Особым видом структур данных является объединение. Определение объединения напоминает определение структуры, только вместо ключевого слова struct используется union:
union number {
short sx;
long lx;
double dx;
};
В отличие от структуры, все атрибуты объединения располагаются по одному адресу. Под объединение выделяется столько памяти, сколько нужно для хранения наибольшего атрибута объединения. Объединения применяются в тех случаях, когда в один момент времени используется только один атрибут объединения и, прежде всего, для экономии памяти. Предположим, нам нужно определить структуру, которая хранит "универсальное" число, т.е. число одного из предопределенных типов, и признак типа. Это можно сделать следующим образом:
struct Value {
enum NumberType { ShortType, LongType,
DoubleType };
NumberType type;
short sx; // если type равен ShortType
long lx; // если type равен LongType
double dx; // если type равен DoubleType
};
Атрибут type содержит тип хранимого числа, а соответствующий атрибут структуры – значение числа.
Value shortVal;
shortVal.type = Value::ShortType;
shortVal.sx = 15;
Хотя память выделяется под все три атрибута sx, lx и dx, реально используется только один из них. Сэкономить память можно, используя объединение:
struct Value {
enum NumberType { ShortType, LongType,
DoubleType };
NumberType type;
union number {
short sx; // если type равен ShortType
long lx; // если type равен LongType
double dx; // если type равен DoubleType
} val;
};
Теперь память выделена только для максимального из этих трех атрибутов (в данном случае dx). Однако и обращаться с объединением надо осторожно. Поскольку все три атрибута делят одну и ту же область памяти, изменение одного из них означает изменение всех остальных. На рисунке поясняется выделение памяти под объединение. В обоих случаях мы предполагаем, что структура расположена по адресу 1000. Объединение располагает все три своих атрибута по одному и тому же адресу.
Рис. 8.1. Использование памяти в объединениях.
Замечание. Объединения существовали в языке Си, откуда без изменений и перешли в Си++. Использование наследования классов, описанное в следующей главе, позволяет во многих случаях добиться того же эффекта без использования объединений, причем программа будет более надежной.