Jump to content

Класс друга

Дружественный класс в C++ может получить доступ к закрытым и защищенным членам класса , в котором он объявлен как дружественный. [1] В значительной степени дружественный класс используется для части структуры данных , представленной классом, для обеспечения доступа к основному классу, представляющему эту структуру данных. Механизм дружественных классов позволяет расширить хранилище и доступ к частям, сохраняя при этом правильную инкапсуляцию , как ее видят пользователи структуры данных.

Подобно дружественному классу, дружественная функция — это функция , которой предоставляется доступ к закрытым и защищенным членам класса, в котором она объявлена ​​как дружественная.

В следующем примере показано использование дружественного класса для структуры данных графа , где граф представлен основным классом Graph, а вершины графа представлены классом Vertex .

#include <iostream>
#include <memory>
#include <string>
#include <unordered_set>

class Graph;

class Vertex {
 public:
  explicit Vertex(std::string name) : edges_(), name_(std::move(name)) {}

  auto begin() const { return edges_.cbegin(); }
  auto end() const { return edges_.cend(); }

  const auto& name() const { return name_; }

 private:
  // Vertex gives access-rights to Graph.
  friend class Graph;

  std::unordered_set<Vertex*> edges_;
  std::string name_;
};

class Graph {
 public:
  ~Graph() {
    while (!vertices_.empty()) {
      auto vertex = vertices_.begin();
      RemoveVertex(*vertex);
    }
  }

  auto AddVertex(const std::string& name) -> Vertex* {
    auto vertex = std::make_unique<Vertex>(name);
    auto iter = vertices_.insert(vertex.get());
    return vertex.release();
  }

  void RemoveVertex(Vertex* vertex) {
    vertices_.erase(vertex);
    delete vertex;
  }

  auto AddEdge(Vertex* from, Vertex* to) {
    // Graph can access Vertex's private fields because Vertex declared Graph as
    // a friend.
    from->edges_.insert(to);
  }

  auto begin() const { return vertices_.cbegin(); }
  auto end() const { return vertices_.cend(); }

 private:
  std::unordered_set<Vertex*> vertices_;
};

Инкапсуляция

[ редактировать ]

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

Важно отметить, что класс не может предоставить себе доступ к частной части другого класса; это нарушит инкапсуляцию. Скорее, класс предоставляет доступ к своим личным частям другому классу, объявляя этот класс дружественным. В примере с графом Graph не может объявить себя другом Vertex. Вместо этого Vertex объявляет Graph другом и таким образом предоставляет Graph доступ к своим частным полям.

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

Альтернативы

[ редактировать ]

Аналогичную, но не эквивалентную функцию языка предоставляет C#. internal Ключевое слово модификатора доступа, которое позволяет классам внутри одной сборки получать доступ к закрытым частям других классов. Это соответствует пометке каждого класса как друга другого в той же сборке; Классы друзей более детализированы.

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

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

Характеристики

[ редактировать ]
  • Дружба не симметрична – если класс A друг класса B, сорт B не является автоматически другом класса A.
  • Дружба не транзитивна – если класс A друг класса Bи класс B друг класса C, сорт A не является автоматически другом класса C.
  • Дружба не передается по наследству – если класс Base друг класса X, подкласс Derived не является автоматически другом класса X; и если класс X друг класса Base, сорт X не является автоматически другом подкласса Derived. Однако, если класс Y друг подкласса Derived, сорт Y также будет иметь доступ к защищенным частям класса Base, так же, как подкласс Derived делает.

См. также

[ редактировать ]
  1. ^ «9 Еще о C++» .
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: d8918e58fdeb4cdf29e438138d5ba234__1711289160
URL1:https://arc.ask3.ru/arc/aa/d8/34/d8918e58fdeb4cdf29e438138d5ba234.html
Заголовок, (Title) документа по адресу, URL1:
Friend class - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)