Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lections_rus.doc
Скачиваний:
31
Добавлен:
06.02.2016
Размер:
1.41 Mб
Скачать

Тема 5. Дружественные функции (friend functions) (2 часа)

Итак, мы уже познакомились с одним из основных правил ООП: память класса (переменные) должны быть защищены от внешнего воздействия, то есть доступ к ним можно получить только с помощью функций-членов данного класса.

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

Зачем это может понадобиться? Например, нам необходимо получить прямой доступ к внутренним данным двух разных классов. Вот здесь-то и возникает проблемка... Рассмотрим тикую проблему на примере.

На прошлом уроке мы с вами обсуждали перегрузку операций. Например,выполним перегрузку умножения объекта класса CVector на число. Если мы захотим сделать это для нашего классаCVector, то прототип функции будет такой:

...

CVector operator* (float);

...

, а реализация - такой:

CVector CVector::operator* (float s)

{

CVector t;

t.m_x=m_x*s;// пусть вектор включает две переменные

t.m_y=m_y*s;

return t;

}

Когда же мы будем испытывать нашу перегруженную операцию * в функции main, то обнаружиться, что мы можем умножать только вектор на число, а число на вектор - нет:

void main(){

CVector a(2,4), b;

float k=1.5;

b=a*k; //верно!

b=k*a; //не верно!

}

Как же быть? Перегрузить операцию * в нашем классе CVector другим способом не получится (так как слева от перегружаемой операции должен находиться экземпляр класса CVector. Он, как известно, передается неявно). Сделать это можно через дружественные функции. Для этого пишем в нашей программе функцию для перемножения числа и вектора (именно в такой последовательности):

CVector operator*(float s, CVector v)

{

CVector t;

t.m_x=s*v.m_x;

t.m_y=s*v.m_y;

return t;

}

Обратите внимание, что у нее, в отличие от функции класса, два параметра. Эта функция существует сама по себе, а не в классе, поэтому перед ней не надо писать имя класса с двойным двоеточием.

Но, так как эта функция внешняя по отношению к классу, у нее нет доступа к переменным m_x и m_y (они же ведь помещены в закрытую часть класса CVector!). Для того, чтобы разрешить нашей функции доступ к переменным класса, класс должен объявить ее своим другом. Делается это так:

class CVector{

friend CVector operator*(float s, CVector v);

...

Все! Теперь в функции main мы можем перемножать как число на вектор, так и вектор на число!

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

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

Главной целью использования дружественных функций и классов является повышение эффективности программы. Дружественные функции и классы могут осуществлять прямой доступ к закрытым полям объекта без использования функций-членов этого класса.Рассмотрим примеры.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]