Приступая к изучению темы Дружественные классы, вам необходимо знать, что такое дружественные функции. Тогда вам намного легче будет все понять и мне не придется повторять то, что уже написано в статье о дружественных функциях. Говоря о дружественных классах, хочу отметить, что иногда удобней не объявлять дружественные функции в теле другого класса, а объявить вместо них дружественный класс. Тогда методы этого дружественного класса, автоматически станут дружественными классу, который предоставляет дружбу.
К примеру, если дружественный класс содержит 5 — 10 методов и каждому из них необходим доступ к приватным элементам другого класса. Тогда, объявив дружественный класс, сам код будет выглядеть компактней. Но если доступ к элементам другого класса необходим только нескольким методам дружественного класса, лучше воспользоваться объявлением дружественных функций. Так наши приватные элементы будут более защищены от случайного внесения в них ошибочных данных. И это действительно важно!
Рассмотрим следующий код программы. В нем мы создадим два класса. Один из них объявим дружественным и, используя его методы, внесем изменения в приватные элементы другого класса.
#include <iostream> #include <string.h> using namespace std; class child; //заранее объявляем класс, который станет дружественным class schoolchild //определяем следующий класс { char name[16]; char surname[16]; int clas; public: schoolchild (char*, char*, int);//конструктор void getData(); friend child;//указываем, что класс дружественный }; // определяем методы класса schoolchild schoolchild::schoolchild(char *n, char *s, int c) { strcpy(name, n); strcpy(surname, s); clas = c; } void schoolchild::getData() { cout << name << " " << surname << "\t" << clas << "-й класс"<< endl; } class child //определяем дружественный класс { public: void changeClas(schoolchild &, int ); void getChangeData(schoolchild); }; // определяем методы класса child void child::changeClas(schoolchild &obj, int newCl) //передаем объект класса и вносим изменения в int clas { obj.clas = newCl; } void child::getChangeData(schoolchild obj) { cout << obj.name << " " << obj.surname << "\t переведен(а) в " << obj.clas << "-й класс\n"; } int main() { setlocale(LC_ALL, "rus"); //создаем объекты класса schoolchild schoolchild visotscaya ( "Маргарита", "Высоцкая", 3); schoolchild semenov ( "Александр", "Семенов", 3); cout << "Список учеников 3-го класса:\n"; visotscaya.getData(); semenov.getData(); child transfer; //создаем объект transfer - перевод в с следующий класс transfer.changeClas(visotscaya, 4); transfer.changeClas(semenov, 4); cout << "\nПеревод в следующий класс:\n"; transfer.getChangeData(visotscaya); transfer.getChangeData(semenov); cout << "\nСписок учеников 4-го класса:\n"; visotscaya.getData(); semenov.getData(); return 0; }
Класс, который будет дружественным, надо объявить до того, как мы укажем в другом классе, что он является дружественным. Так делается, если само определение дружественного класса описано ниже определения класса, который предоставляет «дружбу». В строке 6 объявляем класс child
так как определим его уже ниже в коде, после того как укажем, что он является дружественным классу schoolchild
. Далее определяем класс schoolchild
— строки 8-17. В поле private
этого класса размещены две строки name[16]
, surname[16]
и переменная clas
, которые будут инициализированы сразу при создании объекта в главной функции main
, с помощью конструктора класса, объявленного в строке 14. В строке 16 указываем, что класс child
будет дружественным классу schoolchild
— friend child;
. В определении конструктора класса, используя функцию strcpy
, заполняем значениями строки, а так же инициализируем переменную clas
— строки 19 — 24. Ниже определяем метод класса, который будет выводить все данные на экран — void schoolchild::getData()
.
Строки 31 — 46 — определение класса child
и его методов. Как было видно, в классе schoolchild
явно не указано, что методы класса child
являются дружественными. В нем дружественным объявлен сам класс child
, при этом все его методы автоматически становятся дружественными классу schoolchild
. Поэтому, используя методы дружественного класса child
, мы можем обращаться к элементам класса schoolchild
, даже к приватным, и изменять их значения. Класс child
, для простоты восприятия, содержит всего два метода. Определены они в строках 38 — 46.
Метод void changeClas(schoolchild &, int );
принимает в виде параметров адрес объекта класса schoolchild
(для того чтобы внести изменения в его приватный элемент) и значение типа int
(то значение, которое надо записать в элемент clas
). Второй метод, void getChangeData(schoolchild);
, просто выводит на экран информацию с измененными данными. Строки 53 — 54 — создаем два объекта класса schoolchild
и в скобках задаем значения его элементам. Ниже выводим эти данные на экран. В строке 60 объявляем объект дружественного класса — child transfer;
и через методы класса child
обращаемся к объектам и элементам класса schoolchild
. В подтверждение того, что нам удалось сохранить измененные данные в объектах класса schoolchild
, мы снова выводим данные на экран используя метод getData();
— строки 70 — 71.
Вот, собственно, результат работы нашей программы:
Список учеников 3-го класса:
Маргарита Высоцкая 3-й класс
Александр Семенов 3-й класс
Перевод в следующий класс:
Маргарита Высоцкая переведен(а) в 4-й класс
Александр Семенов переведен(а) в 4-й класс
Список учеников 4-го класса:
Маргарита Высоцкая 4-й класс
Александр Семенов 4-й класс
Для продолжения нажмите любую клавишу . . .
Все, что было задумано, осуществилось — данные приватных элементов изменены и сохранены с помощью методов дружественного класса.
Основная информация, которую необходимо запомнить:
- чтобы объявить класс дружественным, в теле класса, который предоставляет дружбу, перед именем дружественного класса необходимо использовать зарезервированное слово С++ —
friend
; - как и в случае с дружественными функциями, нет разницы, в каком поле класса мы объявим дружественный класс —
private
,public
илиprotected
. Мы все равно сможем обращаться к его методам из главной функцииmain()
; - если определение дружественного класса располагается ниже определения класса, предоставляющего дружбу, то объявить дружественный класс надо выше. Это поможет избежать ошибок при компиляции;
- когда класс объявлен дружественным, все его методы так же становятся дружественными, к тому классу в котором он объявлен. При этом методы класса, который разрешил дружбу не имеют доступа к элементам дружественного класса;
- не следует злоупотреблять и объявлять множество дружественных классов. Помните о том, что мы должны заботься о защите данных. Иногда целесообразней использовать дружественные функции;
Пожалуй, этой информации будет достаточно, чтобы продолжить работу и ваши эксперименты с дружественными классами. Если у вас остались вопросы — задавайте их нам.
Комментарии
asduj
А если не объявлять заранее класс child, то в объявлении класса schoolchild можно написать class