
- •Учебное пособие
- •Введение
- •Объектно-ориентированный подход
- •Объектно-ориентированное программирование Абстрактные типы данных
- •Базовые принципы объектно-ориентированного программирования
- •Простейший ввод и вывод
- •Объект cout
- •Манипуляторы hex и oct
- •Другие манипуляторы
- •Объект cin
- •Операторы для динамического выделения и освобождения памяти (new и delete)
- •Базовые конструкции объектно-ориентированных программ Объекты
- •Понятие класса
- •Конструктор копирования
- •Конструктор explicit
- •Указатели на компоненты класса
- •Встроенные функции (спецификатор inline)
- •Организация внешнего доступа к локальным компонентам класса (спецификатор friend)
- •Вложенные классы
- •Static-члены (данные) класса
- •Указатель this
- •Компоненты-функции static и const
- •Proxi-классы
- •Параметры ссылки
- •Независимые ссылки
- •Практические приемы ограничения числа объектов класса
- •Наследование (производные классы)
- •Конструкторы и деструкторы при наследовании
- •Виртуальные функции
- •Абстрактные классы
- •Виртуальные деструкторы
- •Множественное наследование
- •Виртуальное наследование
- •Перегрузка функций
- •Перегрузка операторов
- •Перегрузка бинарного оператора
- •Перегрузка унарного оператора
- •Дружественная функция operator
- •Перегрузка оператора []
- •Перегрузка оператора ()
- •Перегрузка операторов new и delete
- •Преобразование типа
- •Явные преобразования типов
- •Преобразования типов, определенных в программе
- •Шаблоны Параметризированные классы
- •Передача в шаблон класса дополнительных параметров
- •Шаблоны функций
- •Совместное использование шаблонов и наследования
- •Шаблоны класса и friend
- •Некоторые примеры использования шаблона класса Реализация smart-указателя
- •Классы поддерживающие транзакции
- •Задание значений параметров класса по умолчанию
- •Пространства имен
- •Ключевое слово using как директива
- •Ключевое слово using как объявление
- •Псевдоним пространства имен
- •Организация ввода-вывода
- •Состояние потока
- •Строковые потоки
- •Организация работы с файлами
- •Организация файла последовательного доступа
- •Создание файла произвольного доступа
- •Основные функции классов ios, istream, ostream
- •Основы обработки исключительных ситуаций
- •Перенаправление исключительных ситуаций
- •Исключительная ситуация, генерируемая оператором new
- •Генерация исключений в конструкторах
- •Задание собственной функции завершения
- •Спецификации исключительных ситуаций
- •Задание собственного неожиданного обработчика
- •Иерархия исключений стандартной библиотеки
- •Стандартная библиотека шаблонов (stl) Общее понятие о контейнере
- •Общее понятие об итераторе
- •Категории итераторов
- •Основные итераторы
- •Вспомогательные итераторы
- •Операции с итераторами
- •Контейнерные классы Контейнеры последовательностей
- •Контейнер последовательностей vector
- •Контейнер последовательностей list
- •Контейнер последовательностей deque
- •Ассоциативные контейнеры
- •Ассоциативный контейнер multiset
- •Ассоциативный контейнер set
- •Ассоциативный контейнер multimap
- •Ассоциативный контейнер map
- •Адаптеры контейнеров
- •Адаптеры stack
- •Адаптеры queue
- •Адаптеры priority_queue
- •Пассивные и активные итераторы
- •Алгоритмы
- •Алгоритмы сортировки sort, partial_sort, sort_heap
- •Алгоритмы поиска find, find_if, find_end, binary_search
- •Алгоритмы fill, fill_n, generate и generate_n
- •Алгоритмы equal, mismatch и lexicographical_compare
- •Математические алгоритмы
- •Алгоритмы работы с множествами
- •Алгоритмы swap, iter_swap и swap_ranges
- •Алгоритмы copy, copy_backward, merge, unique и reverse
- •Примеры реализации контейнерных классов Связанные списки
- •Реализация односвязного списка
- •Реализация двусвязного списка
- •Реализация двоичного дерева
- •Литература
- •Вопросы по курсу ооп
- •220013, Минск, п.Бровки, 6.
Перегрузка функций
Одним из подходов реализации принципа полиморфизма в языке С++ является использование перегрузки функций. В С++ две и более функций могут иметь одно и то же имя. Компилятор С++ оперирует не исходными именами функций, а их внутренними представлениями, которые существенно отличаются от используемых в программе. Эти имена содержат в себе скрытое описание типов аргументов. С этими же именами работают программы компоновщика и библиотекаря. По этой причине мы можем использовать функции с одинаковыми именами, только типы аргументов у них должны быть разными. Именно на этом и основана реализация одной из особенностей полиморфизма. Заметим, что компилятор не различает функции по типу возвращаемого значения. Поэтому для компилятора функции с различным списком аргументов – это разные функции, а с одинаковым списком аргументов, но с разными типами возвращаемого значения - одинаковые. Для корректной работы программ последнего следует избегать. Функции, имеющие одинаковые имена, но разные списки аргументов, называются перегруженными. Рассмотрим простой пример перегрузки функции sum, выполняющей сложение нескольких чисел различного типа.
#include "iostream.h"
class cls
{ int n;
double f;
public:
cls(int N,float F) : n(N),f(F) {}
int sum(int); // функция sum с целочисленнным аргументом
double sum(double); // функция sum с дробным аргументом
void see(); // вывод содержимого объекта
};
int cls:: sum(int k)
{ n+=k;
return n;
}
double cls:: sum(double k)
{ f+=k;
return f;
}
void cls:: see()
{cout <<n<<' '<<f<<endl;}
void main()
{ cls obj(1,2.3);
obj.see(); // вывод содержимого объекта
cout <<obj.sum(1)<<endl; // вызов функции sum с целочисл. аргументом
cout <<obj.sum(1.)<<endl; // вызов функции sum с дробным аргументом
}
Результат работы программы:
1 2.3
2
3.3
В тоже время перегрузка функций может создавать проблему двусмысленности. Например:
class A
{ . . .
public:
void fun(int i,long j) {cout<<i+j<<endl;}
void fun(long i,int j) { cout<<i+j<<endl;}
};
main()
{ A a;
a.fun(2,2); // ошибка неизвестно какая из 2 функций вызывается
}
В этом случае возникает неоднозначность вызова функции fun объекта a.
Перегрузка операторов
Имеется ограничение в языках С и С++, накладываемое на операции над известными типами данных (классами) char, int, float и т.д.:
char c,
int i,j;
double d,k;
В С и С++ определены множества операций над объектами c,i,j,d,k этих классов, выражаемых через операторы: i+j, j/k, d*(i+j). Большинство операторов (операций) в С++ может быть перегружено (переопределено), в результате чего расширяется диапазон применения этих операций. Когда оператор перегружен, ни одно из его начальных значений не теряет смысла. Просто для некоторого класса объектов определен новый оператор (операция). Для перегрузки (доопределения) оператора разрабатываются функции, являющиеся либо компонентами, либо friend-функциями того класса, для которого они используются. Остановимся на перегрузке пока только с использованием компонент- функций класса.
Для того чтобы перегрузить оператор, требуется определить действие этого оператора внутри класса. Общая форма записи функции-оператора, являющейся компонентой класса, имеет вид:
тип_возвр_значения имя_класса :: operator #(список аргументов)
{ действия, выполняемые применительно к классу
};
Вместо символа # ставится значок перегружаемого оператора.
Следует отметить, что нельзя перегрузить триадный оператор ”?:.”, оператор ”sizeof” и оператор разрешения контекста ”::”.
Функция operator должна быть либо компонентой класса, либо иметь хотя бы один аргумент типа ”объект класса” (за исключением при перегрузке операторов new и delete).Это позволит доопределить свойства операции, а не изменить их. При этом новое значение оператора будет иметь силу только для типов данных, определенных пользователем; для других выражений, использующих операнды стандартных типов, значение оператора останется прежним.
Выражение a#b, имеющее первый операнд а стандартного типа данных, не может быть переопределено функцией operator, являющейся компонентом класса. Например, выражение a-4 может быть представлено как a.operator-(4), где а – объект некоторого типа. Выражение вида 4-a нельзя представить в виде 4.operator(a). Это может быть реализовано с использованием глобальных функций operator.
Функция operator может быть вызвана так же, как и любая другая функция. Использование операции – лишь сокращенная форма вызова функции. Например, запись вида a=в-с; эквивалентна a=operator-(b,с).