Друг класс в C++

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

class MyClass{
friend class AnotherClass;
private:
       int secret;
}

class AnotherClass{
public:
      void getSecret(MyClass mc){
          return mc.secret;
      }
}

Так что да... в приведенном выше коде это на самом деле будет работать, если вы это сделаете... но в целом, почему вы не можете все время использовать методы получения и установки вместо класса друга? Является ли причиной использования класса "друг" из-за "утомительности"?

3 ответа

Решение

friend для случаев, когда вы не хотите показывать getters / setters / internals всем, а только одному классу. Так что это инструмент для инкапсуляции.

Например, если вы предоставили общественности getSecret в MyClassкаждый может иметь доступ к этой закрытой переменной, даже если он не должен знать об этом. Это нарушает инкапсуляцию. friend есть, чтобы решить эту проблему, так что только те классы, которые должны знать о secret иметь доступ к нему.

Как сказал @nicomp, "это все равно, что дать физическому другу ключ от вашего дома, но вы не знаете, что они с ним сделают". Так что friend класс имеет неограниченный доступ ко всем внутренним компонентам класса, с которым он дружит. Это прискорбно, но ключ (без каламбура) здесь состоит в том, чтобы классы были как можно меньше, чтобы это не стало проблемой, что также соответствовало бы принципу единой ответственности.

Публичный получатель или установщик разрешает доступ кому угодно. У них есть несколько применений, в частности, для поддержки инвариантов классов при изменении какого-либо свойства, но пара getter / setter, которая выглядит как следующий код, не лучше открытых переменных-членов:

class A {
 public:
  int getX() const { return x; };
  void setX(int x_) { x = x_; };
 private:
  int x;
};

getX() а также setX() функции делают только доступ к x, Каждый может их использовать, поэтому любой может изменить значение x, Тогда нет смысла делать это приватным.

Если вместо этого нужно изменить только некоторые классы или функции x, вы можете сделать их друзьями класса A, Это ограничивает доступ только тем друзьям, а не дает его всем.

В качестве таких, friend это инструмент для инкапсуляции, позволяющий инкапсуляции быть шире, чем "просто мой собственный класс" (частные члены) или "только мой класс и классы, которые происходят от него" (защищенные члены). Друг не обязательно должен находиться в одной иерархии классов (он вовсе не должен быть классом; функции могут быть друзьями), но он все же позволяет вам ограничивать доступ только к тем вещам, которые действительно в нем нуждаются.

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

Не забывайте про тестирование...

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

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

Рассмотрим следующий вариант использования, с которым я столкнулся в последнее время: я переделал некоторый код из одного класса в другой. Этот новый класс должен был получить доступ к членам из исходного класса, но я не хотел предоставлять это через общедоступные методы получения, чтобы другие клиенты не возились с ними. В этом случае я действительно приветствовал механизм дружбы C++.

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

Другие вопросы по тегам