Функции, дружественные нескольким классам
Функция может быть дружественной сразу нескольким классам. В приведённом ниже примере решается задача вычисления координат конца заданного вектора, начало которого находится в заданной точке. Файл DotVec.h #include<windows.h> // содержит функцию CharToOem #include<math.h> // содержит математические функции class Vec; // неполное объявление класса вектора class Dot // класс точки { 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 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 EndVec (const Dot & A, const Vec & AB); // функция-член класса Dot // объявление дружественной функции friend void EndVec (const Dot & A, const Vec & AB, Dot & B); • • • class Vec // класс вектора { char name [ 3 ]; // имя вектора double x, y; // проекции вектора public: // конструкторы класса Vec Vec (char * pName) { strncpy (name, pName, 3); x = 0; y = 0; } Vec (char * pName, double X, double Y) { strncpy (name, pName, 3); x = X; y = Y; } Vec (char * pName, Dot A, Dot B); // конструирование вектора по координатам его концов double GetX () const { return x; } double GetY () const { return y; } // вычисляет координаты конца заданного вектора void EndVec (const Dot & A, Dot & B); // функция-член класса Vec // объявление дружественной функции friend void EndVec (const Dot & A, const Vec & AB, Dot & B); • • • Файл DotVec.cpp // три функции вычисляют координаты конца заданного вектора void Dot:: EndVec (const Dot & A, const Vec & AB) // описание функции-члена класса Dot
{ Лекция 4 Дружественные функции и классы x = A.x + AB.GetX (); y = A.y + AB.GetY (); } void Vec:: EndVec (const Dot & A, Dot & B) // описание функции-члена класса Vec { B.SetX (A.GetX () + x); B.SetY (A.GetY () + y); } void EndVec (const Dot & A, const Vec & AB, Dot & B) // описание дружественной функции { B.x = A.x + AB.x; B.y = A.y + AB.y; } Файл Main.cpp void main () { Dot A ('A', 3, 4), B ('B',-3, 4); // вызов конструктора Dot (char Name, double X, double Y) Vec AB ("AB", A, B); // вызов конструктора Vec (char * pName, Dot A, Dot B) Vec AC ("AC", 2, 2); // вызов конструктора Vec (char * pName, double X, double Y) C.EndVec (A, AC); // вызов функции Dot:: EndVec (const Dot & A, const Vec & AB) AC.EndVec (A, C); // вызов функции Vec:: EndVec (const Dot & A, Dot & B) EndVec (A, AC, C); // вызов дружественной функции } // EndVec (const Dot & A, const Vec & AB, Dot & B) Эта программа демонстрирует важный случай применения неполного объявления класса: без применения этой конструкции в данном случае было бы невозможно объявить дружественную функцию для двух классов. Неполное объявление класса Vec дает возможность использовать его имя в объявлении дружественной функции еще до то определения. Необходимо отметить, что при неполном объявлении класса объявления классов должны находиться в одном заголовочном файле, в данном случае DotVec.h. В приведенном примере объявлены классы точки Dot и вектора Vec и поставленная задача решена тремя различными способами. Функция void Dot:: EndVec (const Dot & A, const Vec & AB) является членом класса Dot, получает константные ссылки на вектор и начало вектора и передаёт координаты конца вектора в текущую точку. Поскольку закрытые члены-данные класса Vec недоступны в классе Dot, то мы используем открытые функции-члены класса Vec – GetY () и GetX (). Функция-член класса вызывается оператором: C.EndVec (A, AC), где объект C является текущим, а объекты A и AC – параметрами. Функция void Vec:: EndVec (const Dot & A, Dot & B) является членом класса Vec, получает константную ссылку на начало вектора и ссылку на конец вектора. При вычислениях используются значения проекций текущего вектора. Поскольку закрытые члены-данные класса Dot недоступны в классе Vec, то мы используем открытые функции-члены класса Dot – GetX (), GetY (), SetX (), SetY (). Функция-член класса вызывается оператором: AC.EndVec (A, C), где объект AC является текущим, а объекты A и C – параметрами. Функция friend void EndVec (const Dot & A, const Vec & AB, Dot & B) является дружественной классам Dot и Vec. Для этого она объявлена в обоих классах с ключевым словом friend. Функция получает константные ссылки на начало вектора и вектор, а также ссылку на конец вектора. Поскольку закрытые данные-члены обоих классов Dot и Vec доступны дружественной функции, то мы используем оператор “точка” для доступа к этим данным. Дружественная функция вызывается оператором EndVec (A, AC, C).
|