Правила по отношению к друзьям

1) На описание friend не действуют спецификаторы public, protected, private.

2) Описание friend не взаимное: если А объявляет В другом, то это не означает, что А является другом для В.

3) Дружественность не наследуется. Если А объявляет В другом, то классы, производные от А, не будут автоматически признавать дружественность В.

Лекция 20

Перегруженные операции

Для типов float, double, int, long определены операции +, -, *, /, %, +=, -= и др. Но для типов, которые получены с помощью классов, эти операции надо реализовать самостоятельно. С этой целью можно было бы применить

функции-члены, например: plus ( ) для сложения, plusequal ( ) для += и т.д. Но это неудобно. Значительно лучше применить общеупотребительные знаки +, += и прочие. А для этого надо перегрузить упомянутые или другие операции для объектов описанного класса.

Перегрузить можно любую операцию, кроме следующих: ., .*, ::, ?:.

Это можно сделать двумя способами:

1) С помощью перегруженных операторов – функций, которые являются членами класса;

2) С помощью перегруженных функций, которые являются friend (дружественными функциями) для данного класса.

Рассмотрим первый способ. В этом случае синтаксис для перегруженной операции имеет вид:

имя_класса& operator операция (имя_класса& параметр)

Рассмотрим пример для перегруженной операции += для комплексных чисел.

# include <stdio.h>

Class comp

{

Float Re, Im;

public:

Comp (float a, float b)

{

Re=a;

Im=b;

}

comp& operator += (comp& x)

{

Re+=x.Re;

Im+=x.Im;

return *this;

}

void put_info (char *Str)

{

printf (“%s.Re=%f %s.Im=%f\n”, Str, Re, Str, Im);

}

};

Void main ( )

{

Comp C1 ( 2, -2), C2 (-2, 2);

C1+=C2;

C1.put_info (“C1”);

}

 

В результате перегруженной операции += значение С1 изменится. Ее адрес при вызове операции += был передан в this. Второй параметр был передан в качестве фактического параметра вместо формального х. Результат возвращается через *this. Если нужно сложить два комплексных числа и при этом оставить их значения без изменений, можно использовать второй способ перегрузки операции с помощью дружественной функции. Для этого примера прототип такой функции следующий:

friend comp operator + (comp& C1, comp& C2);

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

# include <stdio.h>

Class comp

{

Float Re, Im;

public:

Comp (float a, float b)

{

Re=a;

Im=b;

}

Comp ( )

{

}

friend comp operator + (comp& C1, comp& C2);

void put_info (char *Str)

{

printf (“%s.Re=%f %s.Im=%f\n”, Str, Re, Str, Im);

}

};

Void main ( )

{

Comp C1 ( 2, -2), C2 (-2, 2);

Comp C3;

C3=C1+C2;

C3.put_info (“C3”);

}

comp operator + (comp& C1, comp& C2);

{

Comp V;

V.Re=C1.Re + C2.Re;

V.Im=C1.Im + C2.Im;

Return V;

}

При перезагрузке операций следует выполнять следующие правила:

1) Приоритеты операций и правила ассоциаций, принятые для типов float, double, int, long, должны оставаться неизменными также и для перегруженных функций-операций;

2) Функции-операции не могут изменить поведение операции по отношению к стандартным типам float, double, int, long;

3) Функция-операция должна быть или элементом класса, или воспринимать один или несколько аргументов, которые имеют тип класса;

4) Функция-операция не может иметь аргументы по умолчанию;

5) За исключением operator = ( ) все функции-операции наследуются.

 

Лекция 21

Статические элементы

Статические элементы-данные

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

static тип имя_элемент-данных.

Например,

Сlass A

{

static int x ; // Объявление

: : : : :

};

int A :: x = 125; //Инициализация

Здесь приведен статический элемент данных целого типа. После завершения описания класса А этот элемент инициализирован. Инициализация обязательна! Элемент данных, определенный как static, используется всеми объектами данного класса. Существует только один экземпляр переменной независимо от числа созданных объектов. На самом деле, память под статический элемент выделяется, даже если не существует ни одного объекта данного класса. Именно потому, что это только один экземпляр, обращение к нему имеет вид:

имя_класса : : имя_элемента=данных.

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