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

Являются ли внутренние классы в С++ автоматически друзьями?

Если я определяю внутренний класс в С++, он автоматически является другом класса, который его содержит? Например, это законно:

class Outer {
public:
    class Inner {
    public:
        void mutateOuter(Outer& o);
    };

private:
    int value;
};

void Outer::Inner::mutateOuter(Outer& o) {
    o.value ++; // Legal?  Or not?
}

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

4b9b3361

Ответ 1

После того, как я задал более или менее тот же вопрос здесь, я хотел поделиться (по-видимому) обновленным ответом для С++ 11:

Цитата из fooobar.com/questions/95494/...:

стандарт $11.7.1

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

и обычные правила доступа указывают, что:

"Член класса может также получить доступ ко всем именам, к которым относится класс имеет доступ..."

в стандарте приведены конкретные примеры:

class E {
    int x;
    class B { };

    class I {
        B b; // OK: E::I can access E::B
        int y;
        void f(E* p, int i) {
            p->x = i; // OK: E::I can access E::x
        }
    };
}

Ответ 2

До С++ 11 (например, С++ 98 и С++ 03)

В С++ 98 и С++ 03 вложенный класс не может получать доступ к private и protected членам окружающего класса по умолчанию.

Стандарт С++ (2003) говорит в $11.8/1 [class.access.nest],

У членов вложенного класса нет специальный доступ к членам класс, а также классы или функции, которые дали дружбу к закрывающему классу; обычно правила доступа (пункт 11) должны быть повиновался. Члены закрывающей класса не имеют специального доступа к члены вложенного класса; обычный правила доступа (пункт 11) должны быть повиновался.

Пример из самого стандарта:

class E 
{
    int x;
    class B { };
    class I 
    {
        B b; // error: E::B is private
        int y;
        void f(E* p, int i)
        {
           p->x = i; // error: E::x is private
        }
   };
   int g(I* p)
   {
       return p->y; // error: I::y is private
   }
};

Так как С++ 11

Вышеуказанное ограничение было удалено с С++ 11. Теперь вложенные классы могут получить доступ к private и protected членам входящего класса:

class E 
{
    int x;
    class B { };
    class I 
    {
        B b; // ok: even though E::B is private
        int y;
        void f(E* p, int i)
        {
           p->x = i; // ok: even though E::x is private
        }
   };
   int g(I* p)
   {
       return p->y; // ok: even though I::y is private
   }
};

Надеюсь, что это поможет.

Ответ 3

Поскольку вопросник, кажется, принял один из ответов, это просто дополнение.
Стандарт, похоже, изменил спецификацию доступности.

§11.8/1 в С++ 98:

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

§11.8/1 в N1804 (после TR1):

Вложенный класс является членом и как таковой имеет те же права доступа, что и любые другой участник.

Я думаю, что текущие компиляторы С++ подчиняются более новой спецификации.

Ответ 4

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

В принципе, вложенность класса определяет определенную область, а не права доступа.

Ответ 5

Этот ответ относится к (устаревшей) спецификации С++ 03. Принятый ответ по этому вопросу более актуальный.

Ну, мне сейчас глупо задавать этот вопрос, потому что я просто нашел соответствующую часть спецификации, которая охватывает это: & sect; 11.8/1:

Члены вложенного класса не имеют специального доступа к членам охватывающего класса, а также к классам или функциям, которые предоставили дружбу окружающему классу; должны соблюдаться обычные правила доступа (раздел 11). Члены закрывающего класса не имеют специального доступа к членам вложенного класса; обычные правила доступа (статья 11) должны соблюдаться

(Мой акцент)

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