Перегрузка стандартных операций

Window w3 (5 ,10 , 400 , 300 )

Перегрузка конструкторов

Void main ( )

{ Men*m = new Men;

m->Name(“ Ivans”);

m-> Age(45);

cout<< m->Name ( )<< “ – “ <<m->Age( );

}

Перегрузка функций действует в пределах их видимости, в пределах класса.

Функции Name( )или Age( ) , объявленные в другом классе, - это совсем другие функции.

Перегрузка обычных функций не дает, каких либо существенных преимуществ, это просто удобно.

 

Перегрузка конструкторов приобретает особое значение, из-за того, что конструктору нельзя назначать произвольное имя, оно всегда должно совпадать с именем класса.

Наличие в классе нескольких конструкторов , имеющих одно имя, но разный состав параметров, возможно благодаря реализации средства перегрузки функций.

Таким образом, перегрузка для конструкторов просто неизбежна.

Мы уже рассматривали несколько конструкторов, которые могут быть включены в класс

 

class A {

int x , y ;

public:

A ( int, int );// конструктор с параметрами для инициализации

// данных

A( );// конструктор по умолчанию

A ( A& ) ;// конструктор копирования

… } ;

Часто при разработке класса предусматривается несколько вариантов инициализации объектов и значит должно быть несколько конструкторов с параметрами:

 

Class Window {

int x;// х-координата начала окна

int y ;// y-координата начала окна

int w ;// ширина окна

int h ;// высота окна

Window ( )// конструктор по умолчанию

{ x = y = 0; w = h= 100 ; }

 

Window ( int w1 , int h1 )// конструктор инициализации размеров окна

{ x = y = 0 ; w = w1; h = h1 ; }

Window ( int x1 , int y1 , int w1, int h1 )// инициализация положения и

{ x = x1; y = y1 ; w = w1 ; h = h1 } //размеров окна

 

Window ( Window & win )// конструктор копирования данных окна

{ x = win.x; y = win.y ; w = win.w ; h = win.h ; }

} ;

Window w1;

Window w2 ( 300 , 250) ;

Window w4 = w3;

Перегрузка операций - это распространение действий стандартных операций на операнды, для которых эти операции не предполагались или предание стандартным операциям другое назначение.

В синтаксисе языка С++ такого правила нет.

 

Например, сложение комплексных чисел предполагает почленное сложение действительных и мнимых частей чисел – слагаемых. Обычная операция ‘ +’ умеет складывать только два числа, а не пару чисел.

Хотелось бы распространить эту операцию для класса комплексных чисел, т. е. придать ей несколько другой смысл, перегрузить операцию.

 

Классы дают такую возможность!

 

Если операнды операции (или хотя бы один) – объекты некоторого класса, т.е. введенного пользователем типа, можно использовать специальную функцию – “операцию – функцию”, определяющую новое поведение операции.

 

Формат определения операции-функции:

<Тип возвращаемого значения > operator <знак операции>

( спецификация формальных параметров)

{ тело операции-функции }

Механизм перегрузки операций во многом схож с механизмом определения функций, если принять что

a) конструкция operator <знак операции>есть имя некоторой функции;

b) список формальных параметров – список операндов с указанием их типов, которые участвуют в операции;

c) тип возвращаемого результата – это тип значения, которое возвращает операция;

d) тело операции-функции –это алгоритмнового действия операции.

 

Часто перегрузка операции не меняет общий смысл операции, однако в некоторых случаях перегрузка совершенно изменяет назначение операции.

Так стандартные операции “>>”и“ << “ - это битовые сдвиги, однако при использовании их с потоковыми объектами эти операции приобретают смысл “ извлечения из потока или переслать в поток ”.

 

Большинство операций перегружаемы, однако, не все.

Операции, не допускающие перегрузки:

. -операция доступа к элементу класса

.*- операция доступак указателю на элемент класса

?: -условная операция

: :- операция разрешения области видимости

sizeof - размер объекта

# -препроцессорное преобразование строк

## -препроцессорная конкатенация строк.

 

Перегрузку можно проводить тремя вариантами:

 

1) операция - функция является компонентной функцией класса;

 

2) операция – функция - глобальная функция :

а) операция - функция является дружественной функцией класса;

 

б) операция - функция является недружественной функцией класса, но

хотя бы один параметр функции (недружественной) был бы объектом некоторого класс или ссылкой на объект.

 

Количество параметров операции-функции определяется арностью операции и тем, является ли функция глобальной или компонентной.

Рассмотрим все эти случаи на примере перегрузки операциясложения‘+’для объектов некоторого классаА.

1) Операция – функция является компонентной функцией класса A.

При этом функция не должна быть статической,так как будет вызываться, и обрабатывать обычные (не статические) данные конкретного объекта.

При определении компонентная функции имеет на один параметр меньше, чем арность операции. Первым операндом такой операции по умолчанию является тот объект, для которого вызывается функция.

Определим такую компонентную функцию внешне, а в классе представим только прототип функции:

Class A {

A operator + ( A obj );

};

A A :: operator + ( A obj)

{тело перегрузки}

Пусть B , C , D -объекты класса A ,выражение B = C+Dследует трактовать как вызов компонентной функции с именем operator+для объекта C:

B= C.operator+ (D);

Таким образом, С– это тот объект, для которого вызывается операция – функция, а объект D– ее параметр.

Бинарная операция “+ “ выглядит не симметрично.

 

 

2) Операция – функция является глобальной функцией и

а) дружественной функцией классу A:

сlass A { …

friend A operator + ( A obj1, A obj2);

};

A operator + ( A obj1, A obj2)

{ тело функции перегрузки}

б)не является дружественной функцией классу A:

class A { … };

A operator + ( A obj1, A obj2)

{ тело функции перегрузки}

Если B, CиD– объектыкласса А, выражение B= C+Dтрактуется каквызов:

B= operator+ (C,D);

где operator+рассматривается как имя функции, C и D – ее параметры.

В случае 2) перегрузка симметрична относительно слагаемых.

 

Следует помнить при написании тела перегрузки, что дружественные функции имеют доступ к закрытым данным класса, а обращение к закрытым данным класса из обычной внешней функции не возможно. Поэтому для перегрузки, как правило, используют дружественные функции.

 

Рассмотрим перегрузку ряда операций для класса Complex:

class Complex {

float re , im ;

public:

Complex ( float, float ) ;// конструктор для инициализации

friend float real (Complex);// функция –друг для получения re

friend float image (Complex);// функция –друг для получения im

Complex operator – ( ) ;// перегрузка одноместной операции ”-” , метод

//класса

Complex operator – ( Complex&) ;// перегрузка двуместной операции

// ”-” , метод класса

friend Complex operator + ( Complex&, Complex&) ;// перегрузка“+”-

//друг

};

Complex :: Complex (float r , float i )

{re = r ; im = i ; }

Complex Complex:: operator-( )

{ return Complex (-re, -im); }

Complex Complex :: operator-( Complex& z) // передача по ссылке , чтобы

{ return Complex (re – z.re, im- z.im); }// не копировать объект в стек

Complex operator+( Complex &z1, Complex &z2)

{ return Complex (z1.re + z2.re , z1.im+ z2.im ) ; }

float real (Complex z){ return z.re ; }

float image (Complex z ){ return z.im ;}