class x
{
void xx() {}
};
class y
{
friend void x::xx();
};
Это приводит к ошибке, как
ошибка: функция друга ‘xx’ является приватным членом ‘x’
Почему я не могу объявить приватную функцию-член другом другого класса?
Имя, назначенное декларацией друга, должно быть доступно в
область действия класса, содержащая объявление друга.
Причина довольно проста; private
Участники должны соблюдать четкое и определенное правило:
Членом класса может быть
private
; то есть его имя может использоваться только членами и друзьями класса, в котором оно объявлено.
Разрешение именования частных членов в объявлениях внутри несвязанных классов нарушило бы это правило: оно позволяет другому классу зависит от деталей реализации без явного разрешения. Это становится проблематичным, например, при изменении имени, типа или подписи частного участника или его полном удалении; это предназначено, чтобы не сломать интерфейс этого класса.
Это можно обойти, сделав весь x
друг y
:
class x {
void xx() {}
};
class y {
friend x;
};
Идея создания x::xx
private
должно быть что x::xx
это деталь реализации, на которую не должны полагаться другие классы. Это не просто означает, что x::xx
не может быть вызван другими классами, это означает, или, скорее, это должно означать, что, например, переименование x::xx
в x::xy
не должен ломать ничего, кроме самого класса и его друзей.
В вашем случае переименование x::xx
в x::xy
вызовет класс y
иметь ошибку, даже если это не друг x
,
Чтобы избежать этого, нужно сделать y
друг x
, чтобы y
может получить доступ x
«s private
члены. Затем он может объявить x::xx
как friend
,
(Примечание: более прямым ответом на вопрос «Почему компилятор не позволяет этого?» Является «Потому что стандарт не позволяет этого». Это естественным образом приводит к последующему вопросу «Почему стандарт этого не допускает?»). «Я пытаюсь ответить на этот вопрос.)