Dot C ('C') ; // вызов конструктора Dot ( char Name )
CharToOem ("Длина отрезка ", S ) ;
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 ), которая получает три ссылки на точки и возвращает значение площади треугольника. Функция вызывается оператором Area ( A , B , С ). Несмотря на то, что функция использует объекты типа Dot, тело функции не содержит обращений к закрытым членам класса. Поэтому мы не стали объявлять функцию как дружественную.
Дружественная функция не является членом класса, в котором она объявлена. Поэтому, вызывая дружественную функцию, не нужно указывать имя объекта или указатель на объект и операцию доступа к члену класса (точку или стрелку). Доступ к закрытым членам класса дружественная функция получает только через объект класса, который, в силу этого, должен быть либо объявлен внутри функции, либо передан ей в качестве аргумента. Дружественная функция не наследуется, то есть она не является таковой для производных классов.
Функции, дружественные нескольким классам
Функция может быть дружественной сразу нескольким классам. В приведённом ниже примере решается задача вычисления координат конца заданного вектора, начало которого находится в заданной точке.