Могут ли внутренние классы обращаться к закрытым переменным? - PullRequest
104 голосов
/ 28 января 2009
class Outer {

    class Inner {
    public:
        Inner() {}
        void func() ;
    };

private:
    static const char* const MYCONST;
    int var;
};

void Outer::Inner::func() {
    var = 1;
}

const char* const Outer::MYCONST = "myconst";

Эта ошибка выводится, когда я компилирую с классом Outer :: Inner ', в котором нет члена с именем `var'

Ответы [ 4 ]

107 голосов
/ 28 января 2009

Внутренний класс является другом класса, в котором он определен.
Так да; объект типа Outer::Inner может получить доступ к переменной-члену var объекта типа Outer.

В отличие от Java, корреляции между объектом типа Outer::Inner и объектом родительского класса нет. Вы должны установить отношения родитель-потомок вручную.

#include <string>
#include <iostream>

class Outer
{
    class Inner
    {
        public:
            Inner(Outer& x): parent(x) {}
            void func()
            {
                std::string a = "myconst1";
                std::cout << parent.var << std::endl;

                if (a == MYCONST)
                {   std::cout << "string same" << std::endl;
                }
                else
                {   std::cout << "string not same" << std::endl;
                }
            }
        private:
            Outer&  parent;
    };

    public:
        Outer()
            :i(*this)
            ,var(4)
        {}
        Outer(Outer& other)
            :i(other)
            ,var(22)
        {}
        void func()
        {
            i.func();
        }
    private:
        static const char* const MYCONST;
        Inner i;
        int var;
};

const char* const Outer::MYCONST = "myconst";

int main()
{

    Outer           o1;
    Outer           o2(o1);
    o1.func();
    o2.func();
}
25 голосов
/ 28 января 2009

Внутренний класс имеет доступ ко всем членам внешнего класса, но у него нет неявной ссылки на экземпляр родительского класса (в отличие от некоторых странностей с Java). Поэтому, если вы передаете ссылку на внешний класс внутреннему классу, он может ссылаться на что угодно во внешнем экземпляре класса.

6 голосов
/ 28 января 2009

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

Редактировать: ваш компилятор правильный, var не является членом Inner. Но если у вас есть ссылка или указатель на экземпляр Outer, он может получить к нему доступ.

1 голос
/ 20 февраля 2012

var не является членом внутреннего класса.

Чтобы получить доступ к var, следует использовать указатель или ссылку на экземпляр внешнего класса. например pOuter-> var будет работать, если внутренний класс является другом внешнего, или, если var является общедоступным, если строго следовать стандарту C ++.

Некоторые компиляторы рассматривают внутренние классы как друга внешних, но некоторые не могут. См. этот документ для компилятора IBM :

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

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

...