Дружественный класс — это когда один класс говорит другому: "Бери мои секреты, ты в деле". В C++ есть private и protected штуки, которые обычно никто не трогает. Но если ты пишешь friend, то другому классу открывается доступ, как будто он свой.
Как это задать?
Пишешь friend class ИмяКласса; внутри того класса, чьи секреты отдаёшь. Всё, теперь этот "друг" может лезть куда угодно в твоём классе.
Код #1: База с коробкой
Вот простой пример, чтобы въехать:
#include <iostream>
class Box {
private:
double width; // Ширина — это секрет
public:
Box(double w) {
width = w; // Задаём ширину
}
friend class Printer; // Printer — наш бро, пускаем его
};
class Printer {
public:
void printBox(Box b) {
// Лезем в секретное поле width, потому что мы друзья
std::cout << "Ширина коробки: " << b.width << std::endl;
}
};
int main() {
Box myBox(15.0); // Коробка с шириной 15
Printer myPrinter; // Создаём принтер
myPrinter.printBox(myBox); // Вывод: Ширина коробки: 15
return 0;
}
Тут Box пускает Printer к своей ширине. Без friend был бы облом — private никто не видит.
Код #2: Человек и доктор
Теперь пример, как будто из жизни:
#include <iostream>
class Person {
private:
int weight; // Вес — личное дело
int age; // Возраст тоже секрет
public:
Person(int w, int a) {
weight = w;
age = a;
}
friend class Doctor; // Доктору можно всё знать
};
class Doctor {
public:
void checkPerson(Person p) {
// Доктор шарит и за вес, и за возраст
std::cout << "Вес: " << p.weight << " кг, возраст: " << p.age << " лет" << std::endl;
}
};
int main() {
Person me(75, 25); // Я вешу 75 кг, мне 25
Doctor doc; // Доктор на связи
doc.checkPerson(me); // Вывод: Вес: 75 кг, возраст: 25 лет
return 0;
}
Тут Doctor шарит за все приватные штуки Person, потому что он в друзьях.
Как это работает?
Ты в классе (например, Box) пишешь friend class Printer;.
Теперь Printer может в своих функциях обращаться к width, как будто это его поле.
Но это работает только в одну сторону — Box не может лезть в Printer, если тот не скажет "ты тоже мой друг".
Код #3: Машина и механик
Ещё пример, чтобы закрепить:
#include <iostream>
class Car {
private:
int mileage; // Пробег — секретный
public:
Car(int m) {
mileage = m;
}
friend class Mechanic; // Механик в деле
};
class Mechanic {
public:
void fixCar(Car c) {
// Механик видит пробег и чинит
std::cout << "Пробег машины: " << c.mileage << " км" << std::endl;
// Допустим, чинит что-то
}
};
int main() {
Car myCar(50000); // Машина с пробегом 50к
Mechanic pro; // Механик готов
pro.fixCar(myCar); // Вывод: Пробег машины: 50000 км
return 0;
}
Механик шарит за пробег, хотя он private, потому что он друг.
Код #4: Два класса с дружбой
А что если два класса помогают друг другу? Вот пример:
#include <iostream>
class Player {
private:
int score; // Очки игрока
public:
Player(int s) {
score = s;
}
friend class Game; // Game — наш кореш
};
class Game {
private:
int level; // Уровень игры
public:
Game(int l) {
level = l;
}
void showStats(Player p) {
// Game видит очки игрока
std::cout << "Уровень: " << level << ", Очки: " << p.score << std::endl;
}
};
int main() {
Player me(100); // У меня 100 очков
Game myGame(5); // Игра на 5 уровне
myGame.showStats(me); // Вывод: Уровень: 5, Очки: 100
return 0;
}
Тут Game видит score из Player, потому что он друг. Но Player не видит level, потому что дружба односторонняя.
Зачем это нужно?
Когда два класса как братья — один хранит данные, другой с ними работает. Например, список и его итератор.
Чтобы не писать кучу функций типа getScore() или getWidth(), а просто дать доступ.
Код #5: Альтернатива без дружбы
Для сравнения, вот как было бы без friend:
#include <iostream>
class Box {
private:
double width;
public:
Box(double w) {
width = w;
}
double getWidth() { // Пришлось бы писать геттер
return width;
}
};
class Printer {
public:
void printBox(Box b) {
std::cout << "Ширина коробки: " << b.getWidth() << std::endl;
}
};
int main() {
Box myBox(15.0);
Printer myPrinter;
myPrinter.printBox(myBox); // Всё ещё работает, но больше кода
return 0;
}
Без friend надо делать геттеры, а с friend — сразу доступ.
Чего остерегаться?
Не делай всех подряд друзьями, а то потеряешь контроль над данными.
Если можно обойтись без friend (например, через геттеры), лучше так и сделать.