Доступность вложенных классов C++
Учитывая следующий код без учета дружбы между двумя классами:
class OutSideClass
{
...
public:
int i_pub;
protected:
int i_pro;
private:
int i_pri;
class InSideClass
{
...
public:
int j_pub;
protected:
int j_pro;
private:
int j_pri;
};
};
Вопрос 1> Правда ли, что OutSideClass может иметь доступ ТОЛЬКО к открытым членам InSideClass?
Вопрос 2> Правда ли, что InSideClass может получить доступ ко всем членам OutSideClass?
Пожалуйста, поправьте меня, если мое понимание неверно.
4 ответа
Вопрос 1> Правда ли, что OutSideClass может иметь доступ ТОЛЬКО к открытым членам InSideClass?
да
Вопрос 2> Правда ли, что InSideClass может получить доступ ко всем членам OutSideClass?
Нет, в C++03. Да, в C++11.
Стандартный текст очень ясно об этом:
Стандарт C++ (2003) говорит в $11,8/1 [class.access.nest],
Члены вложенного класса не имеют специального доступа ни к членам включающего класса, ни к классам или функциям, которые предоставили дружбу включающему классу; должны соблюдаться обычные правила доступа (пункт 11). Члены включающего класса не имеют специального доступа к членам вложенного класса; должны соблюдаться обычные правила доступа (пункт 11).
Однако в стандартной цитате есть один недостаток. В нем говорится, что вложенные классы не имеют доступа к закрытым членам включающего класса. Но в C++ 11 это было исправлено: в C++ 11 вложенные классы действительно имеют доступ к закрытым членам включающего класса (хотя включающий класс по-прежнему не имеет доступа к закрытым членам вложенных классов).
Смотрите этот отчет о дефектах:
Как указывает@Nawaz, вложенные классы в C++03 не имеют специальных прав доступа для членов включающего класса. Однако это ограничение легко обойти, объявив вложенный класс в качестве друга.
class OutSideClass
{
...
class InSideClass
{
...
};
friend class InSideClass;
};
Все, что вложенные классы делают в C++, помещает внутренний класс в пространство имен внешнего класса. Чтобы создать экземпляр InSideClass из функции-члена OutSideClass, я бы просто сделал
InSideClass *instance = new InSideClass();
Если InsideClass был общедоступным, и я хотел создать экземпляр InSideClass из функции, которая не является членом OutSideClass, я бы набрал:
OutSideClass::InSideClass *instance = new OutSideClass::InSideClass();
В отличие от других языков, таких как Java, InSideClass и OutSideClass полностью отделены друг от друга.
Для вложенного класса нет специальных привилегий доступа к вложенному классу.