Класс друга - Friend class

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

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

Пример

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

#включают <iostream>#включают <memory>#включают <string>#включают <unordered_set>учебный класс График;учебный класс Вершина { общественный:  явный Вершина(стандартное::нить имя) : края_(), имя_(стандартное::двигаться(имя)) {}  авто начинать() const { возвращаться края_.cbegin(); }  авто конец() const { возвращаться края_.уступать(); }  const авто& имя() const { возвращаться имя_; } частный:  // Vertex дает права доступа к Graph.  друг учебный класс График;  стандартное::unordered_set<Вершина*> края_;  стандартное::нить имя_;};учебный класс График { общественный:  ~График() {    пока (!вершины_.пустой()) {      авто вершина = вершины_.начинать();      RemoveVertex(*вершина);    }  }  авто AddVertex(const стандартное::нить& имя) -> Вершина* {    авто вершина = стандартное::make_unique<Вершина>(имя);    авто iter = вершины_.вставлять(вершина.получать());    возвращаться вершина.релиз();  }  пустота RemoveVertex(Вершина* вершина) {    вершины_.стереть(вершина);    Удалить вершина;  }  авто AddEdge(Вершина* из, Вершина* к) {    // Graph может получить доступ к закрытым полям Vertex, потому что Vertex объявила Graph как    // друг.    из->края_.вставлять(к);  }  авто начинать() const { возвращаться вершины_.cbegin(); }  авто конец() const { возвращаться вершины_.уступать(); } частный:  стандартное::unordered_set<Вершина*> вершины_;};

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

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

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

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

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

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

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

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

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

  • Дружбы нет симметричный - если класс А классный друг B, учебный класс B не является автоматически другом класса А.
  • Дружбы нет переходный - если класс А классный друг B, и класс B классный друг C, учебный класс А не является автоматически другом класса C.
  • Дружбы нет унаследованный - если класс Основание классный друг Икс, подкласс Полученный не является автоматически другом класса Икс; и если класс Икс классный друг Основание, учебный класс Икс не является автоматически другом подкласса Полученный. Однако если класс Y друг подкласса Полученный, учебный класс Y также будет иметь доступ к защищенным частям класса Основание, так же как подкласс Полученный делает.

Смотрите также

Рекомендации

внешняя ссылка