Перегрузка операций

Полиморфизм

В C++ операции определены для встроенных типов данных. Перегрузка операций - это переопределение действий операций применительно к объектам конкретных классов.

Средствами перегрузки операций являются специальные функции-операции с ключевым словом operator. Синтаксис функции:

tip operator @(t1 per1[,...])//@ - перегружаемая операция

{...} //tip - тип возвращаемого значения

//t1 per1[,...]- параметры функции

Функция-операция характеризуется следующими свойствами:

- перегружает все операции, кроме (.),(.*),(::),(?:); операция присваивания (=) уже предопределена для любого типа;

- наследуется, кроме функции-операции operator=();

- должна быть либо элементом-функцией класса, либо внешней функцией, но дружественной данному классу;

если функция-операция является внешней и дружественной данному классу, то для бинарных операций она должна иметь два параметра, для унарных - один параметр; выражение obj1@obj2 интерпретируется как operator @(obj1,obj2), выражение @obj интерпретируется как operator @(obj);

если функция-операция является элементом-функцией данного класса, то тогда ей передается неявный указатель this на текущий объект класса, т.е. она уже имеет один неявный параметр, и именно первый; поэтому, для бинарных операций она должна иметь один параметр, для унарных - вообще без параметров; выражение obj1@obj2 интерпретируется как obj1.operator@(obj2), т.е. результат заносится в obj1, а выражение @obj интерпретируется как obj.operator@(), т.е. результат заносится в obj;

- обычно использует в качестве параметров ссылки на объекты, а в качестве возвращаемого значения - значение объекта.

Преобразования типов, определяемые классом

Преобразование типов данных является одной их форм полиморфизма. При объектно-ориентированном программировании необходимы средства преобразований, определяемые классом (элементы-функции класса). Функциями преобразований являются: конструкторы преобразования и операции преобразования.

Конструктор преобразования - это конструктор класса с одним аргументом, служащий для преобразования из типа аргумента к типу класса.

Конструктор удобен для преобразования из базового типа в тип класса. Возьмем пример (класс complex) с перегруженной операцией +, рассмотренный выше. Пусть необходимо складывать комплексные числа с вещественными числами с получением комплексных чисел. Для этого требуется преобразование вещественного числа в комплексное число с нулевой мнимой частью. Добавим в класс complex конструктор преобразования с аргументом типа float.

Операция преобразования - это элемент-функция класса, осуществляющая явное преобразование типа класса в другой тип.

Операция преобразования имеет следующие свойства:

- синтаксис операции преобразования напоминает синтаксис перегруженной операции: operator tip() {...},где tip - идентификатор нового типа, в который происходит преобразование;

- не имеет аргументов и типа возвращаемого значения;

- должна быть нестатической элементом-функцией класса;

- наследуется и может быть как virtual.

Операция удобна для преобразования из типа класса в базовый тип. Пусть необходимо складывать комплексные числа с вещественными числами с получением вещественных чисел. Заменим в предыдущем примере в классе complex конструктор преобразования на операцию преобразования с типом float.

Для преобразования объектов одного и того же класса используются конструкторы копирования, задаваемые явно либо по умолчанию. Пусть выполняется операция присваивания: obj2=obj1;, где obj1 и obj2 объекты одного и того же класса. В этом случае никаких преобразований типов не происходит, а выполняется только неявное поэлементное копирование.

Для преобразования объекта одного класса в объект другого класса (без наследования) используются рассмотренные выше функции преобразования: конструктор преобразования и операция преобразования. Пусть требуется преобразовать объект obj1 класса cl1 в объект obj2 класса cl2, т.е.,например, obj2=obj1;. Тогда синтаксис функций преобразования будет иметь вид:

- конструктор класса cl2: cl2::cl2(const cl1&){...}

- операция класса cl1: cl1::operator cl2(){...}

Необходимо иметь одновременно только одну из этих функций преобразования.

Рассмотрим влияние наследования на преобразование объектов базовых и производных классов. При преобразовании объектов производного класса функции преобразования не требуется. Например, при выполнении операции присваивания происходит неявное поэлементное копирование собственной части и наследуемой (базовой) части одного объекта в другой. Пусть obj1 - объект базового класса cl1, obj2 - объект производного класса cl2. Преобразование объекта производного класса в объект базового класса допустимо без функции преобразования: obj1=obj2;,т.е. часть объекта obj2, унаследованная от класса cl1, присваивается объекту obj1.

Преобразование объекта базового класса в объект производного класса не допустимо без функции преобразования: obj2=obj1;, это не допустимо, так как нет функции преобразования. Требуется явное преобразование из типа cl1 в тип cl2, поэтому, надо создать либо конструктор преобразования в классе cl2 (cl2::cl2 (const cl1&) {...}), либо операцию преобразования в классе cl1 (cl1::operator cl2(){...}). Теперь можно преобразование: obj2=obj1;, преобразование из типа cl1 в тип cl2 допустимо.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: