Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по Технологии разработки ПО 2005.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
833.54 Кб
Скачать

Дружественные функции

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

class Int {

private:

int i;

public:

Int() { i=0; }

Int(int ii) { i=ii; }

void show() { cout << i; }

friend Int sum(Int a1, Int a2); // это - не метод, это – дружественная функция

};

//---------------------------------------------------------------------------

int main() {

Int i1(3), i2(7), i3;

i3 = sum(i1, i2);

i3.show();

getch(); return 0;

}

//---------------------------------------------------------------------------

Int sum(Int a1, Int a2) { //классическое определение функции

return (a1.i + a2.i);

}

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

class Beta; //нужно для объявления дружественной func

class Alpha {

private:

int data;

public:

Alpha() : data(3) { } //конструктор без аргументов

friend int func(Alpha, Beta); //дружественная функция

};

//---------------------------------------------------------------------------

class Beta {

private:

int data;

public:

Beta() : data(7) { } //конструктор без аргументов

friend int func(Alpha, Beta); //дружественная функция

};

//---------------------------------------------------------------------------

int func(Alpha a, Beta b) //определение функции

{ return( a.data + b.data ); }

//---------------------------------------------------------

int main() {

Alpha aa;

Beta bb;

cout << func(aa, bb) << endl; //вызов функции, увидим 10

getch(); return 0;

}

В этой программе функция int func(Alpha a, Beta b) объявлена в двух классах с ключевым словом friend , что позволяет объяснить компилятору, что она является дружественной, т.е. имеет доступ к скрытым данным двух классов. Объект каждого класса передаётся как параметр функции func(Alpha, Beta), и функция имеет доступ к скрытым данным обоих классов посредством этих аргументов.

Из-за того, что к классу нельзя обращаться до того, как он объявлен в программе, здесь в начале программы мы объявили класс Beta до класса Alpha с помощью следующего оператора: class Beta; .

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