Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП Лекции PDF / ООП 04 Лек Дружественные функции и классы.pdf
Скачиваний:
64
Добавлен:
15.02.2015
Размер:
306.49 Кб
Скачать

Лекция 4

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

1

Л Е К Ц И Я 4

ДРУЖЕСТВЕННЫЕ ФУНКЦИИ___________________________________________________________ 1

Функции, дружественные одному классу____________________________________________________ 1 Функции, дружественные нескольким классу ________________________________________________ 3 Функции-члены, дружественные другому классу _____________________________________________ 4

ДРУЖЕСТВЕННЫЕ КЛАССЫ ____________________________________________________________ 5

Скажи мне кто твой друг, и я скажу, кто имеет доступ к твоим закрытым данным.

Народная пословица

Концепция инкапсуляции данных – одна из основополагающих концепций ООП. C++ предоставляет возможность обойти эту концепцию с помощью дружественных функций. Однако использовать ее без веских причин не стоит. C++ позволяет объявлять два вида друзей класса: дружественную функцию или дружественный класс.

ДРУЖЕСТВЕННЫЕ ФУНКЦИИ

Функции, дружественные одному классу

Обычный способ доступа к закрытым членам класса – использование открытой функции-члена. Однако C++ поддерживает и другой способ получения доступа к закрытым членам класса – с помощью дружественных функций. Дружественные функции не являются членами класса, но имеют доступ к его закрытым членам. Более того, одна такая функция может иметь доступ к закрытым членам нескольких классов.

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

class Dot

Файл Dot.h

// класс точки

{

 

// закрытые члены класса

 

const char name ;

// имя точки

double x , y ;

// координаты точки

public:

// открытые члены класса

// конструкторы

 

Dot ( char Name) :

name ( Name ) { x = 0 ; y = 0 ; }

Dot ( char Name , double X , double Y ) : name ( Name ) { x = X ; y = Y ; }

// inline функции получения и задания координат

inline double GetX ( ) const

{

return x ;

}

inline double GetY ( ) const

{

return y ;

}

inline void SetX ( double X )

{

x = X;

}

inline void SetY ( double Y )

{

y = Y;

}

//выводит на экран имя и координаты текущей точки void Print ( ) const ;

//возвращает значение расстояния между текущей и заданной точками double Dist ( Dot B ) const ;

//возвращает значение расстояния между двумя заданными точками

friend double Dist ( const Dot & A , const Dot & B ) ;

} ;

// возвращает значение расстояния между двумя заданными точками

double Dist ( Dot* pA , Dot* pB ) ; // функция получает указатели на точки // возвращает значение площади треугольника с заданными вершинами

double Area ( const Dot & A , const Dot & B , const Dot & C ) ;

double Dot :: Dist ( Dot B ) const

Файл Dot.cpp

 

{

 

double X = B . x – x ;

// объявляет и вычисляет

double Y = B . y – y ;

// катеты прямоугольного треугольника

return sqrt ( X*X + Y*Y ) ;

// вычисляет и возвращает значение

}

// гипотенузы прямоугольного треугольника

Выжол Ю.А.

Объектно-ориентированное программирование

// вызов конструктора Dot( char Name, double X, double Y) // вызов конструктора Dot ( char Name )
double X = pA->GetX ( ) - pB->GetX ( ) ; double Y = pA->GetY ( ) - pB->GetY ( ) ; return sqrt ( X*X + Y*Y ) ;
double Dist ( const Dot & A , const Dot & B)
{
double X = A.x - B.x; double Y = A.y - B.y; return sqrt ( X*X + Y*Y ) ;
}
double Dist ( Dot* pA , Dot* pB )
{

Лекция 4

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

2

// объявляет и вычисляет // катеты прямоугольного треугольника

// вычисляет и возвращает значение // гипотенузы прямоугольного треугольника

// объявляет и вычисляет // катеты прямоугольного треугольника

// вычисляет и возвращает значение } // гипотенузы прямоугольного треугольника double Area ( const Dot & A , const Dot & B , const Dot & C )

{

double a = Dist ( B , C ) ;

// объявляет и вычисляет

double b = Dist ( A , C ) ;

// длины сторон треугольника

double c = Dist ( A , B ) ;

 

double p = ( a + b + c ) / 2.0 ;

// объявляет и вычисляет длину полупериметра

return sqrt ( p*(p - a)*(p - b)*(p - c) ) ;

// вычисляет по формуле Герона площадь

}

// треугольника и возвращает её значение

Файл Main.cpp

void main()

{

char S [ 30 ] ;

Dot A ('A', 3 , 4 ) , B ('B', -3 , 4 ) ; Dot C ('C') ;

CharToOem ("Длина отрезка ", S ) ;

cout<<S<<"AB = "<<A . Dist ( B )<<'\n'; // вызов функции Dist ( Dot & A ) const cout<<S<<"BC = "<<Dist ( B , C )<<'\n'; // вызов функции Dist ( const Dot & A , const Dot & B ) cout<<S<<"AC = "<<Dist ( &A , &C )<<'\n';// вызов функции Dist ( Dot* pA , const Dot* pB )

CharToOem ("Площадь треугольника ", S ) ; cout<<S<<"ABC = "<<Area ( A , B , C )<<'\n';

}

В приведённом примере объявлен класс точки Dot и решается задача вычисления расстояния между двумя точками. Задача решена тремя различными способами.

Функция double Dot :: Dist ( Dot B ) const является членом класса Dot и возвращает значение расстояния между текущей и заданной точками. Спецификатор const указывает компилятору, что состояние текущего объекта не должно изменяться. В качестве параметра функция получает целиком объект типа Dot , который занимает в памяти 17 байт. Функция-член класса вызывается оператором: A . Dist ( B ), где объект А является текущим, а объект В – параметром.

Функция friend double Dist ( const Dot & A , const Dot & B ) возвращает значение расстояния между двумя заданными точками. Спецификатор const перед параметрами указывает компилятору, что состояние параметров не должно изменяться. В качестве параметров функция получает две ссылки на объекты типа Dot, которые занимает в памяти по 4 байта каждый. Функция вызывается оператором Dist ( A , B ). Поскольку функция является дружественной классу Dot, то доступ к закрытым членам x и y параметров A и B, которые являются объектами типа Dot, осуществляется с помощью оператора точка, например:

A . x.

Функция double Dist ( Dot* pA , Dot* pB ) возвращает значение расстояния между двумя заданными точками. В качестве параметров функция получает два указателя на объекты типа Dot, которые занимает в памяти по 4 байта каждый. Функция вызывается оператором Dist ( &A , &B ). Поскольку функция не является ни членом класса Dot, ни дружественной классу к нему, то не может получить доступа к закрытым членам x и y параметров A и B. Получить значения членов x и y в этом случае можно только с помощью открытых функций-членов класса GetX ( ) и GetY ( ) соответственно, например: pA->GetX ( ). Обратите внимание на то, что прототип глобальной функции мы расположили за пределами объявления класса.

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

Приведённый выше пример содержит также решение задачи вычисления площади треугольника с помощью глобальной функции double Area ( const Dot & A , const Dot & B , const Dot & C ), которая по-

лучает три ссылки на точки и возвращает значение площади треугольника. Функция вызывается операто-

Выжол Ю.А.

Объектно-ориентированное программирование