C++ для начинающих: Дружественные функции и примеры

Дружественные функции в C++ — это функции, имеющие доступ к закрытым (private) и защищённым (protected) членам класса. Это позволяет обходить ограничения модификаторов доступа, обеспечивая гибкость в работе с классами. Рассмотрим практический пример.

Пример: Классы Person и Car

Создадим два класса: Person, описывающий человека, и Car, описывающий машину. Сначала реализуем их без дружественных функций.

class Car {
private:
    std::string name; // Название машины

public:
    void InfoCar() {} // Метод вывода информации о машине
};

class Person {
private:
    int age;       // Возраст
    std::string name; // Имя

public:
    void InfoCar() {} // Метод вывода информации о машине
};

Теперь создадим функцию, выводящую информацию о владельце машины: «Человек с именем [имя владельца] имеет машину [имя машины]». Попробуем реализовать её без дружественных функций:

void InfoCar(const Car& car, const Person& person) {
    std::cout << "Человек с именем " << person.name << " имеет машину " << car.name << std::endl;
}

Эта функция не скомпилируется, так как name в обоих классах — закрытый член. Доступ к нему напрямую через объекты классов невозможен.

Решение с дружественными функциями

Решим проблему, используя дружественные функции. Создадим функцию InfoCar, объявленную как дружественная для обоих классов:

class Car {
private:
    std::string name;

public:
    Car(const std::string& carName) : name(carName) {}
    friend void InfoCar(const Car& car, const Person& person);
};

class Person {
private:
    int age;
    std::string name;

public:
    Person(const std::string& personName) : name(personName) {}
    friend void InfoCar(const Car& car, const Person& person);
};

void InfoCar(const Car& car, const Person& person) {
    std::cout << "Человек с именем " << person.name << " имеет машину " << car.name << std::endl;
}

Ключевое слово friend перед объявлением функции InfoCar в каждом классе указывает компилятору, что функция дружественна для данного класса и имеет доступ к его закрытым членам. Параметры функции принимаются по константной ссылке (const &), что повышает эффективность передачи больших объектов.

Для корректной компиляции необходимо объявить прототип класса Car перед объявлением класса Person, чтобы избежать ошибки, связанной с неизвестным типом Car в объявлении дружественной функции в классе Person.

Проверка работы кода

Проверим работоспособность кода, создав объекты и вызвав функцию InfoCar:

int main() {
    Car bmw("BMW");
    Person john("John");
    InfoCar(bmw, john); // Выведет: Человек с именем John имеет машину BMW
    return 0;
}

Программа скомпилируется и выполнится, выведя ожидаемый результат. Благодаря дружественным функциям, удалось обойти ограничения модификаторов доступа и реализовать необходимую функциональность.

Дружественные функции — мощный механизм доступа к закрытым членам классов извне, но использовать их следует осторожно. Переизбыток дружественных функций может снизить инкапсуляцию и затруднить сопровождение кода. Внимательно оценивайте необходимость их использования в каждом конкретном случае.

Что будем искать? Например,программа