
Лекция 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 ) ; |
// вычисляет и возвращает значение |
} |
// гипотенузы прямоугольного треугольника |
Выжол Ю.А. |
Объектно-ориентированное программирование |
Лекция 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 ), которая по-
лучает три ссылки на точки и возвращает значение площади треугольника. Функция вызывается операто-
Выжол Ю.А. |
Объектно-ориентированное программирование |