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

В этом уроке мы изучим создание дружественных классов в C++.

В предыдущем уроке мы познакомились с дружественными функциями. Теперь рассмотрим дружественные классы. Они аналогичны дружественным функциям, но предоставляют доступ к приватным членам класса не только одной функции, а всему другому классу.

Классы Dog и Person

Продемонстрируем это на примере класса Dog, описывающего собаку, и класса Person, описывающего человека.

Класс Dog

class Dog {
private:
  int Health = 100; // Уровень здоровья
};

Класс Dog содержит поле Health — уровень здоровья собаки (изначально 100).

Класс Person

class Person {
public:
  void damage(Dog& dog) {
    dog.Health -= 20;
    std::cout << "Health of Animal: " << dog.Health << std::endl;
  }

  void heal(Dog& dog) {
    dog.Health += 10;
    std::cout << "Health of Animal: " << dog.Health << std::endl;
  }

  void kill(Dog& dog) {
    dog.Health = 0;
    std::cout << "Health of Animal: " << dog.Health << std::endl;
  }
};

Класс Person содержит методы damage (наносит урон), heal (восстанавливает здоровье) и kill (убивает собаку). Каждый метод обращается к полю Health класса Dog. Без объявления дружественного класса, обращение к dog.Health вызовет ошибку компиляции, поскольку Health — приватный член класса Dog.

Объявление дружественного класса

Чтобы предоставить классу Person доступ к приватным членам класса Dog, объявим Person дружественным классом для Dog:

class Dog {
private:
  int Health = 100;
  friend class Person; // Объявление Person как дружественного класса
};

Строка friend class Person; внутри определения класса Dog делает весь класс Person дружественным. Теперь методы класса Person могут обращаться к приватным членам класса Dog без ошибок.

Важно: Для корректной работы кода необходимо объявить прототип класса Person перед определением класса Dog, если класс Person объявлен после Dog. Это предотвратит ошибку компиляции, поскольку компилятор должен знать о существовании класса Person перед его использованием в объявлении дружественного класса.

Тестирование кода

Создадим объекты классов Dog и Person и протестируем методы:

int main() {
  Dog Scooby;
  Person Alex;

  Alex.damage(Scooby);
  Alex.damage(Scooby);
  Alex.heal(Scooby);
  Alex.heal(Scooby);
  Alex.kill(Scooby); 

  return 0;
}

Этот код демонстрирует использование методов класса Person для изменения уровня здоровья объекта Scooby класса Dog.

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

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