
- •Учебное пособие
- •Введение
- •Объектно-ориентированный подход
- •Объектно-ориентированное программирование Абстрактные типы данных
- •Базовые принципы объектно-ориентированного программирования
- •Простейший ввод и вывод
- •Объект 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.
Перегрузка оператора []
Как было отмечено выше, функция operator может быть с успехом использована для доопределения операторов С++ (в основном арифметические, логические и операторы отношения). В то же время в С++ существуют некоторые операторы, не входящие в число перечисленных, но которые полезно перегружать. К ним относится оператор []. Его необходимо перегружать с помощью компоненты-функции, использование friend-функции запрещено. Общая форма функции operator[]() имеет вид:
тип_возвр_значения имя_класса::operator [](int i)
{ тело функции}
Параметр функции необязательно должен иметь тип int , но он использован, так как operator[] в основном применяется для индексации. Рассмотрим пример программы с использованием перегрузки операции []:
#include "iostream.h"
class massiv
{ float f[3];
public:
massiv(float i,float j,float k){f[0]=i; f[1]=j; f[2]=k;}
float operator[](int i)
{ return f[i];} // перегрузка оператора []
};
void main()
{ massiv ff(1,2,3);
double f;
int i;
cout << "введите номер индекса ";
cin >> i;
cout <<"f["<< i <<" ]= " << ff[i] << endl;
}
В примере перегруженная функция operator[]() возвращает величину элемента массива, индекс которого передан в функцию в качестве параметра. Данная программа при небольшой модификации может позволить использовать оператор[] как справа, так и слева от оператора присваивания. Для этого необходимо, чтобы функция operator[]() возвращала не элемент, а ссылку на него.
#include "iostream.h"
class massiv
{ float f[3];
public:
massiv(float i,float j,float k){f[0]=i; f[1]=j; f[2]=k;}
float &operator[](int i) // перегрузка оператора []
{ if(i<0 || i>2) // проверка на выход за границы массива
{ cout << “Выход за пределы массива”<<endl;
exit(1);
}
return f[i];
}
};
void main()
{ massiv ff(1,2,3);
int i;
cout << "введите номер индекса ";
cin >> i;
cout <<"f["<< i <<" ]= " << ff[i] << endl;
ff[i]=5; // если функция operator не возвращает ссылку,то компиля-
// тор выдает ошибку =' : left operand must be l-value
cout <<"f["<< i <<" ]= " << ff[i] << endl;
}
Рассмотрим случай когда функция operator возвращает не ссылку, а указатель на модифицируемое значение. Внесем некоторые изменения в рассмотренную выше программу.
class massiv
{ float f[3];
public:
. . .
float *operator[](int i) // перегрузка оператора []
{ . . .
return &f[i];
}
};
void main()
{ massiv ff(1,2,3);
. . .
*ff[i]=5; // функция operator возвращает указатель
cout <<"f["<< i <<" ]= " << *ff[i] << endl;
}
В приведенном примере создается ложное впечатление, что ff является вектором указателей. Поэтому использование ссылки представляется более предпочтительным.
Приведем еще один пример программы, использующей перегрузку operator[].
// перегрузка функции operator[] на примере вычисления n!
#include "iostream.h"
#include "values.h" // для определения константы MAXLONG
class fact
{ long l;
public:
long operator[](int); // перегрузка оператора []
};
long fact::operator[](int n)
{ long l;
for (int i=0; i<=n; i++) //выбор буквы из уменьшаемой строки
if(l>MAXLONG/i)
cerr<<"ОШИБКА факториал числа "<<n<<" больше "<<MAXLONG;
else l*=i;
return l;
}
void main()
{ fact f;
int i,k;
cout << "введите число k для нахождения факториала"
cin >> k;
for (i=1; i<=k; i++)
cout << i <<"! = " << f[i] << endl;
}