Используйте перегрузку операторов только там, где сохраняется их первоначальный смысл, и где это действительно необходимо.
Операторы, за исключением оператора =, наследуются производным классом. Могут перегружаться в производном классе.
Перегрузка операторов – проявление полиморфизма в С++. Перегрузка операторов является одним из видов перегрузки функций. Однако, при этом вводятся дополнительные правила.
Перегрузка операторов должна удовлетворять следующим требованиям:
l не допускается перегрузка операторов со встроенными типами данных в качестве параметров, тип, по крайней мере, одного параметра перегруженного оператора должен быть классом;
l нельзя вводить новые операторы;
l нельзя изменять количество параметров оператора;
l ассоциативность перегруженных операторов не изменяется;
l приоритеты перегруженных операторов не изменяются;
l оператор не может иметь аргументов по умолчанию, за исключением оператора вызова функции ();
l оператор не может иметь неопределенное количество параметров, за исключением оператора вызова функции ().
Как методы класса лучше перегружать операторы, у которых левый аргумент является текущим объектом (например, операции с присваиванием). Если же левым аргументом может быть объект, тип которого отличается от реализуемого типа, такую операцию лучше реализовывать как внешнюю.
Операция | Рекомендуемая форма перегрузки |
Унарные операции | Методы класса |
- [] () -> ->* | Обязательно методы класса |
+= -= *= /= %= &= |= ^= <<= >>= | Метод класса |
Остальные бинарные операции | Внешняя функция |
В языке С++ операторы рассматриваются как функции, имеющие следующий прототип:
Имя_Типа operator@ (список_параметров);
Здесь символом @ обозначено имя оператора
Унарные операторы могут быть перегружены как нестатические члены классабез параметров:
Имя_Типа operator@ ( );
либо как не члены класса с одним параметром:
Имя_Типа operator@ (Имя_Класса &Имя_Параметра);
здесь @ обозначает один из следующих унарных операторов:
& * + - ~ !
Обращение к операции в этом случае выполняется двумя способами:
· инфиксная форма
@ параметр
· функциональная форма
оператор @ (параметр)
Бинарные операторы могут быть перегружены как нестатические члены класса с одним параметром – значением второго (правого) операнда:
Имя_Типа operator@ (Тип_Параметра Имя_Параметра);
либо как не члены класса с двумя параметрами, при этом левый операнд передается первому параметру, а правый - второму:
Имя_Типа operator@ (Тип_Параметра Имя_1, Тип_Параметра Имя_2);
здесь @ обозначает один из следующих бинарных операторов:
+ - * / % == <= >= != && || << >>
Обращение к операции в этом случае выполняется двумя способами:
· инфиксная форма
параметр1 @ параметр2
· функциональная форма
оператор @ (параметр1, параметр2)
Оператор присваивания может быть перегружен только как нестатический член классаи должен иметь следующий прототип:
Имя_Класса& operator= (constИмя_Класса &Имя_Параметра);
l Если оператор присваивания не определен в классе, то компилятор генерирует оператор присваивания по умолчанию, который выполняет почленное копирование атрибутов класса.
l Оператор присваивания целесообразно перегружать только в том случае, если дополнительно к копированию атрибутов нужно выполнить еще какие-либо действия. Как правило, это приходится делать, если объект работает с указателями и динамически выделяет память, чтобы избежать простого копирования указателей (см. ранее пример с конструктором копирования).
l При реализации оператора присваивания следует проверять возможность присваивания объекта самому себе.
Оператор индексирования может быть перегружен только как нестатический член класса с одним параметром – значением индекса:
Имя_Типа& operator[] = (const int& i);
В С++ при перегрузке оператор [] рассматривается как бинарный оператор.
Операторы инкремента ++ и декремента --могут быть перегружены как члены класса без аргументов или как не члены класса с одним аргументом. Для того, чтобы префиксные операторы отличать от постфиксных, в объявлении последних вводят дополнительный фиктивный параметр типа int .
Имя_Класса operator@ (); // префиксный
Имя_Класса operator@ (int); // постфиксный
Имя_Класса operator@ (Имя_Класса &Имя_Параметра );
Имя_Класса operator@ (Имя_Класса &Имя_Параметра ,int);
Оператор вызова функции( ) может быть перегружен только как нестатический члены класса:
Имя_Типа operator@ (список_параметров);
Здесь количество параметров может быть произвольным, и допускается определять значения параметров по умолчанию. Вызывается оператор вызова функции путем применения списка фактических параметров к объекту класса, в котором он определен. Так как в этом случае объект может использоваться как функция, он иногда называется функциональным объектом.
Операторы преобразования типа (конвертор)–функция-член класса, которая преобразует тип объекта класса в некоторый другой тип. Конвертор имеет следующий прототип:
operatorИмя_Типа ();
ЗдесьИмя_Типазадает тип данных (встроенный или пользовательский), к которому приводится объект. Конвертер может вызываться как явно, так и неявно – при преобразованиях типов в выражениях, вызове функций и т.п.
Перегруженные операторы >> и << для ввода и вывода.Для перегрузки определяются как дружественные операторы класса, которые имеют следующие прототипы:
friend istream& operator>>(istream&,Имя_Класса& Имя_параметра);
friend ostream& operator>>(ostream&, constИмя_Класса& Имя_параметра);
АТД
В современных языках программирования пользователю разрешается определять свои типы, которые трактуются в языке практически так же, как встроенные. Такие типы обычно называют абстрактными типами данных (АТД), хотя лучше, пожалуй, их называть просто пользовательскими.
Абстрактный тип данных (АТД – abstract data type) – это множество значений и совокупность операций над этими значениями этого типа, доступ к которым осуществляется только через интерфейс.
Для представления АТД используются структуры данных, которые представляют собой набор переменных, возможно, различных типов данных, объединенных определенным образом.
Создание АТД предполагает полное сокрытие реализации АТД в виде структур данных от пользователя.
Реализация АТД предполагает расширение понятия операции над значениями типа данных с помощью интерфейсных процедур и функций.
Важный инструмент, позволяющий добиться определения операций над АТД – перегрузка операций.
Библиотека стандартных шаблонов STL
Библиотека стандартных шаблонов С++ (Standart Template Library) обеспечивает стандартные классы и функции, которые реализуют наиболее популярные и широко используемые алгоритмы и структуры данных.
В частности, в библиотеке STL поддерживаются вектора (vector), списки (list), очереди (queue), стеки (stack). Определены процедуры доступа к этим структурам данных.
Ядро библиотеки образуют три элемента: контейнеры, алгоритмы и итераторы.
Контейнеры – объекты, предназначенные для хранения других объектов. Например, в класса vector определяется динамический массив, в классе queue – очередь, в классе list – линейный список. В каждом классе-контейнере определяется набор функций для работы с этим контейнером. Например, список содержит функции для вставки, удаления, слияния элементов. В стеке – функции для размещения элемента в стек и извлечения элемента из стеа.
Алгоритмы выполняют операции над содержимым контейнеров. Существуют алгоритмы для инициализации, сортировки, поиска, замены содержимого контейнера.
Итераторы – объекты, которые к контейнерам играют роль указателей. Они позволяют получать доступ к содержимому контейнера примерно так же, как указатели используются для доступа к элементам массива. С итераторами можно работать так же как с указателями.
Существуют 5 типов итераторов.
Итератор | Описание |
Произвольного доступа | Используется для считывания и записи значений. Доступ к элементам произвольный |
Двунаправленный | Используется для считывания и записи значений. Может проходить контейнер в обоих наравлениях |
Однонаправленный | Используется для считывания и записи значений. Может проходить контейнер только в одном наравлении |
Ввода | Используется только для считывания значений. Может проходить контейнер только в одном наравлении |
Вывода | Используется только для записи значений. Может проходить контейнер только в одном наравлении |
Классы-контейнеры, определенные в STL
Контейнер | Описание | Заголовок |
bitset | Множество битов | <bitset> |
deque | Двустороняя очередь | <deque> |
list | Линейный список | <list> |
map | Ассоциативный список для хранения пар (ключ/ значение), где с каждым ключом связано одно значение | <map> |
multimap | Ассоциативный список для хранения пар (ключ/ значение), где с каждым ключом связано два или более значений | <map> |
multiset | Множество, в котором каждый элемент не обязательно уникален | <set> |
priority-queue | Очередь с приоритетом | <queue> |
queue | Очередь | <queue> |
set | Множество, в котором каждый элемент уникален | <set> |
stack | Стек | <stack> |
string | Строка символов | <string> |
vector | Динамический массив | <vector> |
Имена типов элементов, конкретизированных с помощью ключевого слова typedef, входящих в объявление классов-шаблонов:
Согласованное имя типа | Описание |
size_type reference const_reference iterator const_iterator reverse_iterator const_reverse_iterator value_type alIocator_type key_type key_compare value_compare | Интегральный тип, эквивалентный типу size_t Ссылка на элемент Постоянная ссылка на элемент Итератор Постоянный итератор Обратный итератор Постоянный обратный итератор Тип хранящегося в контейнере значения Тип распределителя памяти Тип ключа Тип функции, которая сравнивает два ключа Тип функции, которая сравнивает два значения |
Векторы
Шаблон для класса vector:
template <class T, class Allocator = allocator <T>> class vector
Ключевое слово Allocator задает распределитель памяти, который по умолчанию является стандартным.
Определены следующие конструкторы:
explicit vector(const Allocator &a = Allocator());
explicit vector(size_type число, const T &значение = T(),
const Allocator &a = Allocator());
vector(const vector<T,Allocator>&объект);
template <class InIter>vector(InIter начало, InIter конец,
const Allocator &a = Allocator());
Определены операторы сравнения:
== < <= != > >=
Определен оператор []
Функции-члены класса vector
Функция-член | Описание |
template<class lnlter> void assign (lnlter начало, Inlter конец); template<class Size, class T> void ssign (Size число, const T &значение = T()); reference at(slze_type i); const_reference at(size_type i) const; reference back(); const_reference back() const; iterator begin(); const_iterator begin() const; size_type capacity() const; void clear(); bool empty() const; iterator end(); const_iterator end() const; iterator erase(iterator i); iterator erase (iterator начало, iterator конец); reference front(); const_reference front() const; allocator_type get_allocator() const; iterator insert(iterator i, const T &значение = T()); void insert(iterator i, size_type число, const T &значение); template<class lnlter> void insert(iterator i, Inlter начало, Inlter конец); size_type max_size() const; reference operator[] (size_type i) const; const_reference operator[](size_type ) const; void pop_back(); void push_back(const T &значение); reverse_iterator rbegin(); const_reverse_iterator rbegin() const; reverse_iterator rend(); const_reverse_iterator rend() const; void reserve(size_type число); void resize (size_type число, T значение = T(); size_type size() const; void swap(vector<T, Allocator> &объект); | Присваивает вектору последовательность, определенную итераторами начало и конец Присваивает вектору число элементов, причем значение каждого элемента равно параметру значение Возвращает ссылку на элемент, заданный параметром i Возвращает ссылку на последний элемент вектора Возвращает итератор первого элемента вектора Возвращает текущую емкость вектора, т. е. то число элементов, которое можно разместить в векторе без необходимости выделения дополнительной области памяти Удаляет все элементы вектора Возвращает истину, если вызывающий вектор пуст, в противном случае возвращает ложь Возвращает итератор конца вектора Удаляет элемент, на который указывает итератор i. Возвращает итератор элемента, кoтoрый расположен следующим за удаленным Удаляет элементы, заданные между итераторами начало и конец. Возвращает итератор элемента, который расположен следующим за последним удаленным Возвращает ссылку на первый элемент вектора. Возвращает распределитель памяти вектора Вставляет параметр значение перед элементом, заданным итератором i. Возвращает итератор элемента Вставляет число копий параметра значение перед элементом, заданным итератором i Вставляет последовательность, определенную между итераторами начало и конец, перед элементом, заданным итератором i Возвращает максимальное число элементов, которое может храниться в векторе Возвращает ссылку на элемент, заданный параметром i Удаляет последний элемент вектора Добавляет в конец вектора элемент, значение которого равно параметру значение Возвращает обратный итератор конца вектора Возвращает обратный итератор начала вектора Устанавливает емкость вектора равной, по меньшей мере, параметру число элементов Изменяет размер вектора в соответствии с параметром число. Если при этом вектор удлиняется, то добавляемые в конец вектора элементы получают значение, заданное параметром значение Возвращает хранящееся на данный момент в векторе число элементов Обменивает элементы, хранящиеся в вызывающем векторе, с элементами в объекте объект |
Списки
Шаблон для класса list:
template <class T, class Allocator = allocator <T>> class list
Ключевое слово Allocator задает распределитель памяти, который по умолчанию является стандартным.
Определены следующие конструкторы:
explicit list(const Allocator &a = Allocator());
explicit list(size_type число, const T &значение = T(),
const Allocator &a = Allocator());
list(const list<T,Allocator>&объект);
template <class InIter>list(InIter начало, InIter конец,
const Allocator &a = Allocator());
Определены операторы сравнения:
== < <= != > >=
Функции-члены класса list
Функция-член | Описание |
template<class lnlter> void assign(lnlter начало,Inlter конец); template<class Size, class T> void assign (Size число,const T &значение = T()); reference back(); const_reference back() const; iterator begin(); const_iterator begin() const; void clear(); bool empty() const; iterator end(); const_iterator end() const; iterator erase(iterator i); iterator erase(iterator начало, iterator конец); reference front(); const_reference front() const; allocator_type get_allocator() const; iterator insert(iterator i, const Т &значение = Т()); void insert(iterator i, size_type число, const T &значение); template<class inIter> void insert (iterator i, InIter начало, InIter конец); size_type max_size() const; void merge(list<T, Allocator> &объект); template<class Comp> void merge (list < T, Allocator> &объект, Comp ф_сравн); void pop_back(); void pop_front(); void push_back(const T &значение); void push_front(const T &значение); reverse_iterator rbegin(); const_reverse_iterator rbegin() const; void remove(const T &значение); template<class UnPred> void remove_if(UnPred пред); reverse_iterator rend(); const_reverse_iterator rend() const; void resize(size_type число,T значение = T()); void reversed; size_type size() const; void sort(); template<class Comp> void sort Comp ф_сравн); void splice(iterator i, list<T, Allocator> &объект); void splice(iterator i, list<T, Allocator> &объект, iterator элемент); void splice(iterator i, list<T, Allocator> &объект, iterator начало, iterator конец); void swap(list<T, Allocator> &объект); void unique(); template<class BinPred> void unique(BinPred пред); | Присваивает списку последовательность, определенную итераторами начало и конец Присваивает списку число элементов, причем значение каждого элемента равно параметру значение Возвращает ссылку на последний элемент списка Возвращает итератор первого элемента списка Удаляет все элементы списка Возвращает истину, если вызывающий список пуст, в противном случае возвращает ложь Возвращает итератор конца списка Удаляет элемент, на который указывает итератор i. Возвращает итератор элемента, который расположен следующим за удаленным Удаляет элементы, заданные между итераторами начало и конец. Возвращает итератор элемента, который расположен следующим за последним удаленным Возвращает ссылку на первый элемент списка Возвращает распределитель памяти списка Вставляет параметр значение перед элементом, заданным итератором i. Возвращает итератор элемента Вставляет число копий параметра значение перед элементом, заданным итератором i Вставляет последовательность, определенную между итераторами начало и конец, перед элементом, заданным итератором i Возвращает максимальное число элементов, которое может храниться в списке Выполняет слияние упорядоченного списка, хранящегося в объекте объект, с вызывающим упорядоченным списком. Результат упорядочивается. После слияния список, хранящийся в объекте объект становится пустым. Во второй форме для определения того, является ли значение одного элемента меньшим, чем значение другого, может задаваться функция сравнения ф_сравн Удаляет последний элемент списка Удаляет первый элемент списка Добавляет в конец списка элемент, значение которого равно параметру значение Добавляет в начало списка элемент, значение которого равно параметру значение Возвращает обратный итератор конца списка Удаляет из списка элементы, значения которых равны параметру значение Удаляет из списка значения, для которых истинно значение унарного предиката пред Возвращает обратный итератор начала списка Изменяет размер списка в соответствии с параметром число. Если при этом список удлиняется, то добавляемые в конец списка элементы получают значение, заданное параметром значение Выполняет реверс (т. е. реализует обратный порядок расположения элементов) вызывающего списка Возвращает хранящееся на данный момент в списке число элементов Сортирует список. Во второй форме для определения того, является ли значение одного элемента меньшим, чем значение другого, может задаваться функция сравнения ф_сравн Вставляет содержимое объекта объект в вызывающий список. Место вставки определяется итератором i. После выполнения операции объект становится пустым Удаляет элемент, на который указывает итератор элемент, из списка, хранящегося в объекте объект, и сохраняет его в вызывающем списке. Место вставки определяется итератором i Удаляет диапазон элементов, обозначенный итераторами начало и конец, из списка, хранящегося в объекте объект, и сохраняет его в вызывающем списке. Место вставки определяется итератором i Обменивает элементы из вызывающего списка с элементами из объекта объект Удаляет из вызывающего списка парные элементы. Во второй форме для выяснения уникальности элементов используется предикат пред |
Ассоциативные списки
Шаблон для класса map:
template <class key, class T , class Comp=less<Key>,
class Allocator = allocator <T>> class map
Ключевое слово Allocator задает распределитель памяти, который по умолчанию является стандартным. Key – данные типа ключ, T – тип данных, Comp – функция для сравнения двух ключей (по умолчанию стандартная объект-функция less() ).
Определены следующие конструкторы:
explicit map(const Comp &ф_сравн = Comp(),
const Allocator &a = Allocator());
map(const map<Key, T, Comp, Allocator>&объект);
template <class InIter>map(InIter начало, InIter конец,
const Comp &ф_сравн = Comp(),
const Allocator &a = Allocator());
Определены операторы сравнения:
== < <= != > >=
В ассоциативном списке хранятся пары ключ/значение в виде объектов типа pair.
Шаблон объекта pair:
template <class Ktype, class Vtype> struct pair
{
typedef Ktype первый_тип; // тип ключа
typedef Vtype второй_тип; // тип значения
Ktype первый; // содержит ключ
Vtype второй; // содержит значение
// конструкторы
pair();
pair(const Ktype &k, Vtype &v);
template<class A, class B> pair(const <A,B> &объект);
}
Создавать пары ключ/значение можно с помощью функции:
template<class Ktype, class Vtype> pair(Ktype, Vtype>
make_pair()(const Ktype &k, Vtype &v);
Функции-члены класса map
Функция-член | Описание |
iterator begin(); const_iterator begin() const; void clear(); size.type count (const key_type &k) const; bool empty() const; iterator end(); const.iterator end() const; pair<iterator, iterator> equal_range (const key_type pair <const_iterator, const_iterator> equal_range(const key_type &k) const; void erase(iterator i); void erase (iterator начало,iterator конец); size_type erase (const key_type &k); iterator find. (const key_type &k); const_iterator find (const key_type &k) const; allocator_type get_allocator() const; iterator insert(iterator i, const value_type &значение); template<class lnlter> void insert (InIter начало,InIter конец); pair<iterator, bool>insert (const value_type &значение); key_compare key_comp() const; iterator lower_bound (const key_type &k); const.iterator lower_bound (const key_type &k) const; size_type max_size() const; reference operator[] (const key_type &i); reverse_iterator rbegin(); const_reverse_iterator rbegin() const; reverse_iterator rend(); const_reverse_iterator rend() const; size_type size() const; void swap(map<Key, T, Comp, Allocator> &объект); iterator upper_bound (const key_type &k); const_iterator upper_bound (const key_type &k) const; value_compare value_comp() const; | Возвращает итератор первого элемента ассоциативного списка Удаляет все элементы ассоциативного списка Возвращает 1 или 0, в зависимости от того, встречается или нет в ассоциативном списке ключ к Возвращает истину, если вызывающий ассоциативный список пуст, в противном случае возвращает ложь Возвращает итератор конца ассоциативного списка Возвращает пару итераторов, которые указывают на первый и последний элементы ассоциативного списка, содержащего указанный ключ к Удаляет элемент, на который указывает итератор i Удаляет элементы, заданные между итераторами начало и конец Удаляет элементы, соответствующие значению ключа к Возвращает итератор по заданному ключу к. Если ключ не обнаружен, возвращает итератор конца ассоциативного списка Возвращает распределитель памяти ассоциативного списка Вставляет параметр значение на место элемента или после элемента, заданного итератором i. Возвращает итератор этого элемента Вставляет последовательность элементов, заданную итераторами начало и конец Вставляет значение в вызывающий ассоциативный список. Возвращает итератор вставленного элемента. Элемент вставляется только в случае, если такого в ассоциативном списке еще нет. При удачной вставке элемента функция возвращает значение pair<iterator, true>, в противном случае — pair<iterator, false> Возвращает объект-функцию сравнения ключей Возвращает итератор первого элемента ассоциативного списка, ключ которого равен или больше заданного ключа к Возвращает максимальное число элементов, которое можно хранить в ассоциативном списке Возвращает ссылку на элемент, соответствующий ключу i Если такого элемента не существует, он вставляется в ассоциативный список Возвращает обратный итератор конца ассоциативного списка Возвращает обратный итератор начала ассоциативного списка Возвращает хранящееся на данный момент в ассоциативном списке число элементов Обменивает элементы из вызывающего ассоциативного списка с элементами из объекта объект Возвращает итератор первого элемента ассоциативного списка, ключ которого больше заданного ключа к Возвращает объект-функцию сравнения значений |
Алгоритмы