Являются ли внутренние классы в C ++ автоматически друзьями? - PullRequest
65 голосов
/ 16 февраля 2011

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

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), этот код не будет работать, но я слышал по крайней мере анекдотически, что он работает на некоторых компиляторах. Я не могу найти соответствующий раздел в спецификации C ++ по этому поводу, и если кто-то может процитировать что-то конкретное, что скажет, что это или не законно, что было бы здорово.

Ответы [ 5 ]

64 голосов
/ 07 февраля 2013

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

Цитируется из https://stackoverflow.com/a/14759027/1984137:

standard $ 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
        }
    };
}
37 голосов
/ 16 февраля 2011

До C ++ 11 (т.е. C ++ 98 и C ++ 03)

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

Стандарт C ++ (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

Вышеуказанное ограничение было снято с C ++ 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
   }
};

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

16 голосов
/ 16 февраля 2011

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

§11.8 / 1 в C ++ 98 состояниях:

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

§11.8 / 1 в N1804 (после TR1) гласит:

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

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

4 голосов
/ 16 февраля 2011

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

Что ж, я чувствую себя глупо, задавая этот вопростеперь, потому что я только что нашел соответствующую часть спецификации, которая покрывает это: §11.8 / 1:

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

(мой акцент)

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

3 голосов
/ 16 февраля 2011

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

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

...