Объектно-ориентированное программирование на C++, страница 6
Описание файла
PDF-файл из архива "Объектно-ориентированное программирование на C++", который расположен в категории "". Всё это находится в предмете "информатика" из 1 семестр, которые можно найти в файловом архиве МГТУ им. Н.Э.Баумана. Не смотря на прямую связь этого архива с МГТУ им. Н.Э.Баумана, его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "информатика" в общих файлах.
Просмотр PDF-файла онлайн
Текст 6 страницы из PDF
Если объект – константный, то к нему применимы только константные методы!Удобно реализовать бинарные арифметические операции через уже реализованные операции составного присваивания:const A & A :: operator + ( const A & other ) const {return A (* this ) += other ;}А вот так делать не надо (лишний вызов конструктора копий + вызов деструктора):const A A :: operator + ( const A & other ) const {A result = * this ; result += other ;return result ;}72 / 99Перегрузка операций сравненияБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийВведениеПрисваиваниеБинарныеоперацииУнарные операцииОперация ()ИсключенияОперации сравнения при перегрузке имеют следующие прототипы:boolboolboolboolboolbooloperator ==operator !=operator <operator >operator <=operator >=( const( const( const( const( const( constAAAAAA& other )& other )& other )& other )& other )& other )const ;const ;const ;const ;const ;const ;При этом удобно при реализации одних операций сравненияиспользовать уже реализованные другие операции.
Например, реализовав операцию «==», мы можем использовать еёотрицание в коде операции «!=»:const bool A :: operator != ( const A & other ) const {return !(* this == other );}Этот приём, в частности, автоматически обеспечиваетнепротиворечивость реализации операций сравнения.73 / 99Перегрузка операций с помощью функцийБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийВведениеПрисваиваниеБинарныеоперацииУнарные операцииОперация ()ИсключенияПерегруженные операции могут иметь операнды разныхтипов. Это полезно, например, при реализации операцииумножения матрицы на скалярное значение:const Matrix & operator * ( int k ) const ;Однако, использование такой операции возможно только вслучае, когда матрица является первым операндом.
Чтобысправиться с этой проблемой, в C++ разрешена перегрузкаопераций с помощью функций. Например, в нашем случаефункция умножения скалярного значения на матрицу может выглядеть какconst Matrix & operator * ( int k , const Matrix & m ) {return m * k ;}Следует иметь в виду, что хотя бы один операнд функции,осуществляющей перегрузку операций, должен быть объектом класса. Это гарантирует невозможность перегрузки74 / 99операций над встроенными типами.Перегрузка операций «&&» и «||»БазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийВведениеПрисваиваниеБинарныеоперацииУнарные операцииОперация ()ИсключенияОперации «&&» и «||» могут быть перегружены точно также, как и другие бинарные арифметические операции:const A & operator && ( const A & other ) const ;const A & operator || ( const A & other ) const ;Однако, перегрузка операций «&&» и «||» не рекомендуется.Дело в том, что эти операции применительно к встроеннымтипам данных вычисляют свой второй операнд не всегда.Эта их особенность широко используется в программировании, т.е.
любой программист ожидает, что они будут работать именно по этой схеме.Перегруженные версии этих операций всегда будут вычислять оба операнда. Тем самым, их использование будет контринтуитивно, что обязательно приведёт к ошибкам в программах.75 / 99Перегрузка операции «[ ]»БазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийВведениеПрисваиваниеБинарныеоперацииУнарные операцииОперация ()ИсключенияОперация «[ ]» перегружается следующим образом:тип1 & operator [] ( тип2 index );Операция возвращает ссылку, что даёт возможность использовать её результат в левой части операции присваивания.К сожалению, таким образом перегруженную операциюневозможно применять к константным объектам.
Поэтомупринято определять ещё и специальную версию операции«[ ]» для константных объектов:const тип1 & operator [] ( тип2 index ) const ;Естественно, в этом случае необязательно, чтобы операциявозвращала ссылку. Поэтому, если «тип1» допускает дешёвое копирование, от ссылки можно избавиться.
Например,double operator [] ( int index ) const ;Отметим, что операция «[ ]» не может быть перегружена спомощью функции.76 / 99Перегрузка унарных операцийБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийВведениеПрисваиваниеБинарныеоперацииУнарные операцииОперация ()ИсключенияУнарные операции перегружаются по одной из приведённыхсхем (далее «@» – некоторый знак операции):class A{...тип operator@ ();...};тип operator@ ( A & obj );// с помощью метода// с помощью функцииИсключение составляют постфиксные ++ и --.
Чтобы их отличать от префиксных инкремента и декремента, они имеютдополнительный фиктивный параметр типа int:class A{...A & operator ++ ( int );...};A & operator ++ ( A & obj , int );77 / 99Перегрузка операций «*» и «->»БазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийВведениеПрисваиваниеБинарныеоперацииУнарные операцииОперация ()ИсключенияПерегрузка операций «*» и «->» позволяет использоватьобъекты класса так, как если бы они были указателями:class A{...тип & operator * ();тип operator - > ();...};тип & operator * ( A & a );Особенностью операции «->» является тот факт, что онапоследовательно применяется к своему же возвращаемомузначению до тех пор, пока не получится указатель.
Т.е., например, если в классе A операция «->» возвращает ссылкуна объект класса B, а в классе B операция «->» возвращаетуказатель на объект класса C, то применение «->» к переменной x типа A открывает доступ к полям и методам объекта класса C.78 / 99Пример: перегрузка операции «->»БазовыесведенияОбобщённоепрограммированиеПерегрузкаопераций123456Введение7Присваивание8Бинарныеоперации910Унарные операции11Операция ()12Исключенияstruct C { int field ; };13struct B {C c;C * operator - > ();};C * B :: operator - > () { return & c ; }struct A {B b;B & operator - > ();};1415B & A :: operator - > () { return b ; }16171819202122int main (){A x;x - > field = 666;return 0;}79 / 99Перегрузка операции «&»БазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийВведениеПрисваиваниеБинарныеоперацииУнарные операцииОперация ()ИсключенияПерегрузка операции «&» позволяет вместо адреса объектавозвращать всё, что угодно (например, «умный» указатель,т.е.
объект с перегруженными операциями «*» и «->», осуществляющий подсчёт ссылок на объект и автоматическоеего удаление при уничтожении последней ссылки):class A{...тип operator & ();...};тип operator & ( A & a );Впрочем, перегрузка этой операции не рекомендуется, т.к.может привести к трудноуловимым ошибкам в коде.
Вместо её перегрузки рекомендуется определить метод, которыйделает то же самое, но не экранирует стандартную реализацию «&»:тип address_of ();80 / 99Перегрузка операции приведения типаБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийПерегрузка операции приведения объекта к некоторому типу осуществляется путём объявления методаoperator тип () const ;Например,ВведениеПрисваиваниеБинарныеоперацииУнарные операцииstruct A {int x ;operator int () const ;};Операция ()ИсключенияA :: operator int () const { return x ; }Обратите внимание на то, что, хотя операция приведениятипа возвращает значение, в её объявлении тип возвращаеиого значения не указывается.
В этом она напоминает конструктор.81 / 99Перегрузка операции «( )»БазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийВведениеПрисваиваниеБинарныеоперацииУнарные операцииОперация ()ИсключенияПерегрузка операции ( ) даёт возможность «вызывать»объекты класса, как если бы они были функциями. Прототип перегруженной операции ( ) выглядит кактип operator ()( список формальных параметров );Можно сказать, что операция ( ) – n-арная, потому чтовнутри скобок может располагаться произвольное количество формальных параметров.Естественно, в классе можно определить несколько перегруженных операций ( ), если они будут различаться сигнатурами.82 / 99Оператор throwБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exceptionВ отличие от языка Java, в качестве исключения в C++ может выступать любое значение (объект, строка, значениебазового типа и т.п.).Для порождения исключения предназначен оператор throw,который может вызываться как с указанием значения, описывающего исключительную ситуацию, так и без его указания:throw значение ;throw ; // вариант без указания значенияМеханизм исключений в C++ не предусматривает запоминание информации о стеке вызовов в момент порожденияисключения.
Поэтому сообщение, выводимое при аварийномзавершении программы по причине необработанного исключения, менее информативно.83 / 99Пример: оператор throwБазовыесведенияОбобщённоепрограммированиеПерегрузкаопераций12345int main (){throw ;return 0;}Вывод:Исключенияterminate called without an active exceptionПорождениеПерехват иобработкаСпецификацияКласс exception123456int f ( int x ) { return 2* x ; }int main (){throw f ;return 0;}Вывод:terminate called after throwing an instanceof ’ int (*)( int ) ’84 / 99Синтаксис try- и catch-блоковБазовыесведенияОбобщённоепрограммированиеПерегрузкаоперацийИсключенияПорождениеПерехват иобработкаСпецификацияКласс exceptionКак и в языке Java, участки кода, в которых ожидается возникновение исключительной ситуации, обрамляются tryблоками. С try-блоками связаны один или несколько catchблоков, осуществляющих перехват исключений по типу:try {/* ...