Предисловие: В ответе ниже я имею в виду некоторые различия между C ++ 98 и C ++ 03. Однако оказывается, что изменения, о которых я говорю, еще не вошли в стандарт, поэтому C ++ 03 в этом отношении на самом деле не отличается от C ++ 98 (спасибо Йоханнесу за то, что указал на это). Каким-то образом я был уверен, что видел это в C ++ 03, но на самом деле его там нет. Тем не менее, проблема действительно существует (см. Ссылку на DR в комментарии Йоханнеса), и некоторые компиляторы уже реализуют то, что они, вероятно, считают наиболее разумным решением этой проблемы. Таким образом, ссылки на C ++ 03 в тексте ниже не верны. Пожалуйста, интерпретируйте ссылки на C ++ 03 как ссылки на некоторую гипотетическую, но весьма вероятную будущую спецификацию этого поведения, которую некоторые компиляторы уже пытаются реализовать.
Важно отметить, что произошло значительное изменение в правах доступа для вложенных классов между стандартами C ++ 98 и C ++ 03.
В C ++ 98 вложенный класс не имел специальных прав доступа к членам включающего класса. Это был в основном полностью независимый класс, только что объявленный в объеме вложенного класса. Он мог получить доступ только к public членам включающего класса.
В C ++ 03 вложенному классу были предоставлены права доступа для членов включающего класса в качестве члена включающего класса. Точнее, вложенному классу были предоставлены те же права доступа , что и у статической функции-члена включающего класса. То есть теперь вложенный класс может обращаться к любым членам включающего класса, включая private .
По этой причине вы можете наблюдать различия между разными компиляторами и версиями одного и того же компилятора в зависимости от того, когда они внедрили новую спецификацию.
Конечно, вы должны помнить, что объект вложенного класса никоим образом не связан с каким-либо конкретным объектом включающего класса. Что касается реальных объектов, то это два независимых класса. Чтобы получить доступ к нестатическим членам данных или методам включающего класса из вложенного класса, у вас должен быть определенный объект включающего класса. Другими словами, еще раз, вложенный класс действительно ведет себя так же, как статическая функция-член включающего класса: у него нет определенного указателя this
для включающего класса, поэтому он не может получить доступ к нестатические члены включающего класса, если только вы не приложите усилия, чтобы предоставить ему конкретный объект включающего класса для доступа. Без него вложенный класс может обращаться только к typedef-именам, перечислениям и статическим членам включающего класса.
Простой пример, иллюстрирующий разницу между C ++ 98 и C ++ 03, может выглядеть следующим образом
class E {
enum Foo { A };
public:
enum Bar { B };
class I {
Foo i; // OK in C++03, error in C++98
Bar j; // OK in C++03, OK in C++98
};
};
Это изменение именно то, что позволяет вашей функции PrivDerived::Nested::fred
компилироваться. Он не пройдет компиляцию в педантичном компиляторе C ++ 98.