내부 클래스가 개인 변수에 액세스 할 수 있습니까?


117
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 '라는 멤버가 없습니다.

답변:


120

내부 클래스는 정의 된 클래스의 친구입니다.
그렇습니다. 유형의 객체는 유형 객체의 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();
}

14
기술적으로 현재 C ++ 표준에서 중첩 클래스는 둘러싸는 클래스에 대한 특별한 액세스 권한이 없습니다. 표준의 섹션 11.8.1을 참조하십시오. 그러나이 표준 결함도 참조하십시오 : open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45
Greg Rogers

1
그 가치에 대해 GCC는 제안 된 해결책을 따르고 다른 컴파일러도 그렇게 할 것입니다.
Greg Rogers

24
C + 11 표준은 이제 위의 설명을 준수합니다.
Martin York

1
Java에서 비 정적 내부 클래스는 내부 클래스가 처음 액세스 될 때 외부 클래스의 인스턴스에 대한 참조 (포인터)를 암시 적으로 제공합니다. 이것을 다시 표현하기 위해 jvm은 @LokiAstari가 그의 답변에서 우리에게 보여준 것과 유사한 코드를 암시 적으로 작성하고 있습니다. 다음은 Effective Java 2nd Ed "항목 22 : 비 정적보다 정적 멤버 클래스 선호" 에서 발췌 한 것입니다 . "이 수정 자 (내부 클래스를 선언 할 때 정적 키워드)를 생략하면 각 인스턴스는 둘러싸는 인스턴스에 대한 외부 참조를 갖게됩니다.
데이비드 리

3
@Loki Astari : 저는 마지막 문장 "당신은 부모 자식 관계를 수동으로 만들어야합니다"를 읽고 그 뒤에 나오는 코드 조각을 올바르게 수행하는 방법의 예로 해석했습니다 !
Brent Baccala

32

내부 클래스는 외부 클래스의 모든 멤버에 액세스 할 수 있지만 부모 클래스 인스턴스에 대한 암시 적 참조는 없습니다 (Java의 이상한 점과 달리). 따라서 외부 클래스에 대한 참조를 내부 클래스에 전달하면 외부 클래스 인스턴스의 모든 것을 참조 할 수 있습니다.


7
이 11 C ++에서 사실이다
thrantir

6

아무거나 부분 외부의 공공 또는 개인 외부의 구성원 모두에 액세스 할 수 있어야합니다.

편집 : 컴파일러가 정확하고 var는 Inner의 구성원이 아닙니다. 그러나 Outer의 인스턴스에 대한 참조 나 포인터가 있으면 액세스 할 수 있습니다.


2

var는 내부 클래스의 멤버가 아닙니다.

var에 액세스하려면 외부 클래스 인스턴스에 대한 포인터 또는 참조를 사용해야합니다. 예를 들어 pOuter-> var는 내부 클래스가 외부의 친구이거나 var가 공용이면 C ++ 표준을 엄격하게 따르는 경우 작동합니다.

일부 컴파일러는 내부 클래스를 외부의 친구로 취급하지만 일부는 그렇지 않을 수도 있습니다. IBM 컴파일러에 대해서는 이 문서를 참조하십시오 .

"중첩 된 클래스는 다른 클래스의 범위 내에서 선언됩니다. 중첩 된 클래스의 이름은 둘러싸는 클래스에 국한됩니다. 명시 적 포인터, 참조 또는 객체 이름을 사용하지 않는 한, 중첩 된 클래스의 선언은 다음과 같은 가시적 구조 만 사용할 수 있습니다. 둘러싸는 클래스 및 전역 변수의 형식 이름, 정적 멤버 및 열거 자.

중첩 된 클래스의 멤버 함수는 일반 액세스 규칙을 따르며 둘러싸는 클래스의 멤버에 대한 특별한 액세스 권한이 없습니다. 둘러싸는 클래스의 멤버 함수는 중첩 클래스의 멤버에 대한 특별한 액세스 권한이 없습니다. "


4
잘못된. 다른 답변보기-3 년 전. "만약 C ++ 표준을 엄격히 따르는 경우", 그들은 당신과 다른 답을 얻습니다. C ++ 11의 초기 초안에서 중첩 클래스는 참조 / 포인터를 통해 부모의 모든 멤버에 액세스 할 수 있습니다 . friend또는 을 명시 적으로 선언 할 필요가 없습니다 public. 과거에 IBM이 잘못된 링크에서 잘못되었거나 구식이었던 경우 누가 신경 쓰나요? 이 답변은 게시되기 3 년 전에 이미 구식입니다.
underscore_d

1

우선, varC ++에서 허용되지 않는 클래스 외부의 비 정적 멤버에 액세스하려고합니다 .

Mark의 대답이 맞습니다.

Outer의 일부인 모든 것은 외부의 모든 구성원 (공개 또는 비공개)에 액세스 할 수 있어야합니다.

당신은 두 가지, 하나 선언 할 수 그래서 var등을 static또는 액세스 'VAR'의 (a 때문에 외부 클래스의 인스턴스의 참조를 사용하는 친구 클래스 또는 함수는 또한 액세스 개인 데이터에 대한 참조를 필요로).

정적 변수

클래스의 인스턴스와 연결 하지 않으려는 경우로 변경 var합니다 .staticvar

#include <iostream>

class Outer {

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

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

int Outer::var = 0;

void Outer::Inner::func() {
    std::cout << "var: "<< Outer::var;
}

int main() {
  Outer outer;
  Outer::Inner inner;
  inner.func();

}

출력-var : 1

비 정적 변수

객체의 참조는 비 정적 멤버 변수에 액세스해야합니다.

#include <iostream>

class Outer {

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

public:
   class Inner {
    public:
        Inner(Outer &outer) {
          outer.var = 1;
        }
        void func(const Outer &outer) ;
    };
};

void Outer::Inner::func(const Outer &outer) {
    std::cout << "var: "<< outer.var;
}

int main() {
  Outer outer;
  Outer::Inner inner(outer);
  inner.func(outer);

}

출력-var : 1

편집-외부 링크는 내 블로그에 대한 링크입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.