Подтвердить что ты не робот

Почему функция участника PRIVATE не может быть функцией друга другого класса?

class x
{
    void xx() {}
};

class y
{
    friend void x::xx();
};

Это приводит к ошибке типа

error: функция friend 'xx' является частным членом 'x'

Почему я не могу объявить частную функцию-член как друга другого класса?

4b9b3361

Ответ 1

[class.friend]/9:

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

Причина довольно проста; Члены private должны соблюдать ясное и определенное правило:

Член класса может быть

  • private; то есть его имя может использоваться только членами и друзьями класса, в котором он объявлен.

Разрешить имена частных членов в объявлениях внутри несвязанных классов будет нарушать это правило: он позволяет другому классу зависеть от детализации реализации, не будучи явно разрешенным. Это становится проблематичным, например, при изменении имени частного лица, типа или подписи или его полного удаления; который предназначен для того, чтобы не нарушить интерфейс этого класса.

Это можно обойти, сделав все x другом y:

class x {
    void xx() {}
};

class y {
    friend x;
};

Демо.

Ответ 2

Предполагается, что идея x::xx private заключается в том, что x::xx представляет собой деталь реализации, на которую не следует полагаться другими классами. Это не просто означает, что x::xx нельзя вызывать другими классами, это означает, или, скорее, это должно означать, что, например, переименование x::xx в x::xy не должно нарушать ничего, кроме самого класса и друзей класса.

В вашем случае переименование x::xx до x::xy приведет к ошибке класса y, хотя это не является другом x.

Чтобы избежать этого, сделайте y другом x, так что y может получить доступ к x private членам. Затем он может объявить x::xx как friend.

(Примечание: более прямой ответ на вопрос "Почему компилятор не разрешает это?" - это "Потому что стандарт не позволяет этого". Это, естественно, приводит к следующему вопросу "Почему стандарт не разрешите это?". Я пытаюсь ответить на этот последующий вопрос.)