Распространяется ли «дружеский» класс на классы, объявленные в этом классе? - PullRequest
15 голосов
/ 12 мая 2011

У меня есть следующий код, где класс A объявляет класс B как друга.Должен ли класс C, объявленный в классе B, иметь возможность просматривать частные объявления / члены класса A?

. Он компилируется без ошибок с CL версии 16 (Visual Studio 2010), но gcc g ++ версии 4.1.1 даетошибка "typedef int A :: T является частной в этом контексте".

То же поведение происходит с вызовами функций как typedefs (как я обнаружил разницу).

class A {
   friend class B;
   typedef int T;
};

class B {
   A::T t; // ok
   typedef A::T U; // ok
   class C {
      U u; // ok
      A::T v; // compile error on gcc
   };
};

Iкраткий поиск, но не смог найти правильные условия поиска.Я еще не прочитал стандарт.Есть ли какие-либо предыдущие вопросы по этому вопросу или они упоминались в FAQ по C ++?Какое поведение подразумевается стандартом, если либо?

Ответы [ 3 ]

9 голосов
/ 12 мая 2011

из стандартных документов. $11.4.2

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

Пример из стандартных документов. Сами

class A {
class B { };
friend class X;
};
struct X : A::B { // OK: A::B accessible to friend
    A::B mx; // OK: A::B accessible to member of friend
    class Y {
        A::B my; // OK: A::B accessible to nested member of friend
    };
};

Следовательно, он должен работать без ошибок.

4 голосов
/ 12 мая 2011

Кажется, есть некоторый дефект в исходном стандарте C ++ 03

В соответствии с C ++ 03 [pre CD1] ваш код не должен компилироваться, поскольку формулировка и пример говорят о том, что частные члены класса (предоставление дружбы) не могут быть доступны во вложенном члене класса друга.

C ++ 11 приводит тот же пример, что и в C ++ 03. Единственное изменение, внесенное в этот пример, заключается в том, что вложенный член (класс) класса друга может получить доступ к закрытому члену класса, предоставляющему дружбу.

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

Также посмотрите на выпуск # 45

1 голос
/ 10 июня 2011

Prasoon упомянул проблему # 45 ... это поведение меняется в C ++ 0x.Старое поведение было (11.7 [class.access.nest] параграф 1):

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

Это ясно говорит о том, что gcc 4.1 является верным в соответствии с правилами C ++ 03.gcc 4.5 и MSVC2010 используют правила C ++ 0x.

...