- •Базовое ядро языка Элементы программы.
- •Комментарии
- •Инструкция – выражение
- •Инструкция
- •Определение функции
- •Заголовок функции
- •Прототипы функций
- •Аргументы по умолчанию.
- •Перегрузка функций
- •Встраиваемые функции
- •Стек до блока Вошли в блок Вышли из блока
- •Индексирование
- •Int a [100]; одномерный массив
- •Int b [3][5]; двухмерный массив
- •Int c [7][9][2]; трехмерный массив
- •Передача массивов функциям
- •Объявления ссылок и вызовов по ссылке
- •Функции-члены класса
- •Доступ: закрытый и открытый
- •Область видимости класса
- •Оператор разрешения области видимости ::
- •Вложенные классы
- •Статические члены данных
- •Указатель this
- •Функции-члены типа static и const.
- •Изменчивость (mutable)
- •Создание и уничтожение объектов
- •Классы с конструкторами
- •Конструкторы как преобразования
- •Создание динамического стека
- •Классы с деструкторами
- •Пример: динамически размещаемые строки
- •Ad hoc полиморфизм
- •Алгоритм выбора перегруженной функции
- •Перегрузка операторов
- •Перегрузка бинарных операторов
- •Перегрузка операторов присваивания и индексирования
- •Перегруженные операторы ввода-вывода « и »
- •Перегрузка оператора ( ) для индексирования
- •Операторы указателей
- •Указатель на член класса
- •Перегрузка new и delete
- •Наследование.
- •Методология объективно-ориентированного проектирования
- •Виртуальные функции
- •Абстрактные базовые классы
Перегрузка бинарных операторов
Вернемся к нашему примеру clock и покажем, как перегрузить бинарные операторы. В основном, поддерживаются те же принципы. Когда бинарный оператор перегружается с помощью функции-члена, он получает в качестве первого аргумента неявно передаваемую переменную класса, а в качестве второго аргумента — единственный аргумент списка параметров. Дружественные функции и обычные функции получают оба аргумента из списка параметров (отсутствует неявный аргумент). Конечно, обычные функции не имеют доступа к закрытым членам.
Создадим операцию для типа clock, которая складывает два значения.
class clock { . . . . . friend clock operator +(clock c1, clock c2) ; };
clock operator+(clock cl, clock c2)
{ return (cl.tot_secs + c2.tot_secs) ; }
Целое выражение неявно преобразуется к типу clock с помощью преобразующего конструктора clock ::clock (unsigned long). Оба значения типа с lock передаются как аргументы функции, и оба они являются кандидатами для преобразования при присваивании. Поскольку operator+ () является симметричным бинарным оператором, аргументы должны трактоваться одинаково. Таким образом, обыкновенно симметричные бинарные операторы перегружаются дружественными функциями.
Перегрузка операторов присваивания и индексирования
Оператор присваивания для типа класса по умолчанию генерируется компилятором для выполнения почленного присваивания. Это прекрасно, когда подходит поверхностное копирование. Для типов вроде my_string или vect, которые
нуждаются в глубоком копировании, это некорректно. В качестве практического правила можно принять следующее: каждый раз, когда класс нуждается в явно определенном копирующем конструкторе, он нуждается и в определении оператора присваивания.
Оператор индексирования обычно перегружается, когда тип класса представляет агрегат, для которого предназначено индексирование. Операция индексирования должна возвращать ссылку на элемент, содержащийся в агрегате. Перегрузка присваивания, также как и перегрузка индексирования, обладают некоторыми похожими свойствами. Обе они выполняются как нестатические функции-члены и обе обычно содержат возвращаемый тип-ссылку.
Обновленный класс будет содержать несколько улучшений, делающих его более безопасным и полезным. Будет до6авлен конструктор, преобразующий обычный целый массив в безопасный массив. Это позволит нам написать код, использующий безопасные массивы, а затем эффективно применять этот код с обычными массивами. Наконец, оператор индексирования перегружается и заменяет функцию-член . Перегруженный оператор индексирования может иметь любой возвращаемый тип и любой тип списка аргументов.
Перегруженные операторы ввода-вывода « и »
Сохраняя дух ООП, важно перегрузить оператор «, чтобы выводить пользовательские типы, так же как и собственные. Оператор « имеет два аргумента: ostream& и АТД, и должен создавать ostream&. Используется ссылка на поток и возвращается ссылка на поток (вне зависимости от того, что перегружается — « или »), потому, что мы не хотим копировать объект потока.
Перегрузка оператора » для вывода пользовательского типа обычно выглядит так:
istream& operator»(istream& р, пользовательский_тип& x)
Если функции необходим доступ к закрытым членам x, ее надо сделать дружественной к этому классу. Ключевой момент здесь — сделать х параметром-ссылкой, чтобы его значение можно было изменять. Для этого в классе необходимо поместить объявление friend для этого оператора и обеспечить определение его функции: istream& operator»(istream& in, rational& x)
{ return (in » x.a » x.q); }
