2013-07-15 5 views
3

일부 SO 문서를 검색했지만 아직 내 질문에 대한 답변을 찾지 못했습니다. 이 답변이 이미 어딘가에 존재한다면 죄송합니다.C++ 중첩 클래스

첫번째 배경의 비트 ...

나는 기능은 계층 적 트리 구조를 가지고 기능 "섹션"으로 장치를 표현하고 싶다.

DeviceReferenceCheck(), 
DeviceRefereceSet(), 
DevicePhaseSetX(), 
DevicePhaseDefaultsSet...() 

처럼 평평한 기능의 부하를 가지고보다는 내가

dev.reference.check() 
dev.reference.set() 
dev.phase.setx() 
dev.phase.defaults.set...() 

내가 얻을 중첩 클래스를 사용하기 위해 노력하고있어이 작업을 수행하려면 얻을 수 있도록 내가 대신 중첩 된 클래스를 활용하고 싶습니다 obj.func.subfunction.subsub....() 구조. 중첩 된 클래스는 거기에 제공된 읽기/쓰기 함수를 사용해야하기 때문에 가장 바깥 쪽 클래스에 대한 참조가 필요합니다.

필자가 시도해 보았을 때 가장 잘 이해하지 못하는 것은 다음과 같다. 나는 스스로 시도했지만 컴파일러 경고 때문에 사용을 중단했다.

class GPIBDevice_Agilent53132A : public GPIBDevice 
{ 
private: 
    class RefOsc { 
    public: 
     // ... snip ... 
     RefOsc(GPIBDevice_Agilent53132A &parent); 
     // ... snip ... 
    } ro; 
public: 
    // ... snip ... 
    GPIBDevice_Agilent53132A(); 
    // ... snip ... 
}; 

GPIBDevice_Agilent53132A::GPIBDevice_Agilent53132A() : GPIBDevice(), ro(*this) 
{ 
} 

컴파일러의 말 : gpibdevice_agilent53132a.cpp(5): warning C4355: 'this' : used in base member initializer list.

아하, 내 생각에 ... 똑똑한 컴파일러 ... 초기화 자 목록에 this을 사용하면 클래스가 아직 완벽하게 구성되지 않았기 때문에 아마 좋은 생각이 아닙니다.

질문 1 : 위의 내용이 맞습니까? 둘러싸는 클래스의 initialiser 목록에있는 this을 사용하여 중첩 된 클래스에 둘러싸인 클래스에 대한 참조를 제공하겠습니까? 내 생각은 "예"이지만 다른 SO 스레드에서이 메서드가 사용 된 것을 보았 기 때문에 명확한 설명을 원합니다 (Nested Class member function can't access function of enclosing class. Why?).

내 접근 방법은 중첩 된 멤버 포인터를 가진 다음 실제로 생성자에있을 때 (이제 클래스가 생성 될 때 안전하게 사용할 수 있음) 참조 포인터를 전달할 수있는 새로운 내부 클래스를 만든 것입니다. * 경고없이. 이것이 표준 방법인가요?

....

민간 중첩 된 클래스의 이유에 계속하는 것은 내가 사용자가/클래스에게 자신을 그에게 인스턴스화 할 수 싶지 않아 BTW입니다. 이제는 public으로 시작했는데 ... 중첩 된 클래스에서 private 생성자를 사용하려고 시도했지만 컴파일러에서 클래스를 생성 할 수 없다고 말했습니다. 따라서 둘러싸는 클래스는 중첩 클래스 개인 데이터 멤버를 볼 수 있습니까?

질문 2 : 왜 둘러싸는 클래스가 개인 데이터 멤버/함수 중첩 클래스를 볼 수 없습니까?

이 문제를 해결하려면 내포 된 클래스가 포함 된 클래스를 친구로 선언해야합니다. 이게 정말 필요한가요?

도움 주셔서 감사합니다. curiously recurring template pattern 그의 설명은 Jan

+2

이니셜 라이저 목록에서 'this'를 사용하는 것은 좋은 생각이 아닙니다. 아직 구성되지 않은 클래스 멤버에 액세스하면 프로그램이 중단 될 수 있기 때문입니다. 당신이 미래의 사용을 위해 포인터를 저장하는 것이라면 아무런 문제가 없을 것입니다. – mkirci

+0

기본 클래스 매개 변수가 참조 만 저장하는 경우 안전합니다. 그럴 경우 곧바로 나쁜 생각이라고 부르지는 않겠지 만, 뭔가 잘못되었다는 표시 일 수 있으므로 신중히 디자인을 살펴볼 것입니다. –

+0

감사합니다. 이 문제를 해결하기위한 나의 접근 방식은 중첩 된 멤버 포인터를 가진 다음 생성자에 실제로있을 때 클래스를 생성 할 때 안전하게 사용할 수 있도록하는 멤버 포인터를 갖는 것이 었습니다. 'new' 내부 클래스를 만들었습니다. 여기서' *이 경고없이 '. 이것이 표준 방법인가요? 내가 언급했던 다른 SO 스레드는 어떻게 사용 되는가? – Jimbo

답변

2

요약

감사합니다.알고있는 흥미로운 방법입니다.

질문에 직접 답변한다고 생각하기 때문에 직접 답변을 수락했습니다. CRTP 방법은 좋지만 1 & 2 질문에 직접 응답하지는 않지만 좋은 대안을 제공합니다.

질문 1 :

이 가능하다는 것을 보인다. 컴파일러에서 경고를 생성 한 이유와 그것을 무시하는 것이 "안전한지"에 대한 의문을 확인해 주신 mkirciR. Martinho Fernandes에 감사드립니다.

요약 ... 클래스가 아직 생성되지 않았기 때문에 생성자의 초기화 프로그램 목록에 this을 사용하는 것이 가장 좋습니다. 사람들이 지적했듯이 포인터가 사용되면 UB가 발생할 수 있습니다. 내부 클래스에 대한 포인터를 사용하는 내 작품을 사용하기로 결정한 다음 외부 클래스 생성자 내부에서 한 번만 생성하기로 결정했습니다. 외부 클래스가 이미 생성되어 자체에 대한 참조를 내부로 전달할 수 있습니다. 안전한 수업.

질문 2 : 등이이 같은 중첩 된 클래스가 구성원 인

과 : C++ 표준에서

, 나는 섹션 11.7에서 (파고를 많이 후) 발견 다른 회원과 동일한 액세스 권한. 엔 클로징 클래스의 멤버는 중첩 클래스의 멤버에 특별한 액세스 권한이 없습니다. 일반적인 접근 규칙 (11 절)을 준수해야한다. 내 외부 클래스는 내부 클래스 '개인 생성자를 호출 할 수없는 이유

class E { 
    int x; 
    class B { }; 
    class I { 
     B b; // OK: E::I can access E::B 
     int y; 
     void f(E* p, int i) { 
      p->x = i; // OK: E::I can access E::x 
     } 
    }; 

    int g(I* p) { 
     return p->y; // error: I::y is private 
    } 
}; 

그래서,이 (성가 시게)입니다 :

표준

다음 예제를했다. 내 솔루션은 외부 클래스를 내부 클래스의 친구로 만드는 것이 었습니다. 위의 예제에서 내부 클래스 선언에 friend E;을 추가합니다.