2016-08-23 5 views
46

D 클래스가 컴파일 되나 클래스가 C 인 이유는 무엇입니까? C++의 개인 템플릿 클래스에서 생성자 상속

class A 
{ 
    public: 
     A(int) {} 
}; 

template <class T> 
class B : private T // Note: private base class 
{ 
    public: 
     using T::T; 
}; 

class C : public B<A> 
{ 
    public: 
     C() : B<A>(123) {} // Error: 'class A A::A' is inaccessible 
};       //   within this context 

using BA = B<A>; 

class D : public BA 
{ 
    public: 
     D() : BA(123) {} // OK 
}; 

나는 GCC, Clang 및 Visual C++ 테스트, 그들은 모두 동일합니다. class B : private Tpublic T으로 변경하면 문제가 해결됩니다. 하지만 왜? 합니다 ( using T::Tpublic 유의).

+0

핫스팟을 첨부하기 위해 "템플릿"태그를 추가했습니다. 저에게 "태그 스패밍"에 대한 비판을 보내주십시오. – Bathsheba

+0

그것은 템플릿 태그를 정당화 할 것이고 실제로 클래스 템플릿에서 이름 검색은 미묘하게 다릅니다. – MSalters

답변

42

클래스 A 그 범위 내에 주입 된 클래스 이름 A 포함 (즉, 그 생성자를 참조 할 일이없는 한 A::A 클래스 A 지칭).

B 클래스 상속이, B의 범위 내 이름이 AA의 범위에 주입 클래스 이름 A 지칭되도록. 그러나 AB의 개인 기본 클래스이므로 A의 범위에있는 모든 이름은 B 내에 비공개입니다.

클래스 C은 다시 상속하지만 B 내에 비공개이므로 A에 액세스 할 수 없습니다. 따라서 오류. 이 오류는 실제로 구조에서 A 이름을 사용하는 것과 같습니다. 정의 B<A>는 모든 클래스의 범위에 포함되지 않기 때문에 이름 A 어떤 주입-클래스 이름으로 전역 이름 A을 의미하지 않도록

클래스 BA은이 문제를 가지고 있지 않습니다. 물론 BA이라는 이름은 공개됩니다.

쉽게 C에 이름 A 자격으로이 문제를 해결 할 수 있습니다 생성자 상속이 아무런 효과가 없다는 것을

class C : public B<A> 
{ 
public: 
    C() : B<::A>(123) {} 
}; 

참고. 문제는 클래스 이름 A (A에 삽입되고 BC에 상속 됨)에 대한 액세스로 생성자에 대한 액세스가 아니라 문제입니다.

+1

그래서, (가난한) 다른 용어에서, 오류는 _wrong_ 네임 스페이스 (즉, 클래스'B')에서 A라는 이름에 액세스하려고 시도하고 있다는 것입니다. 샤피. 정말 흥미로운. – skypjack

+0

해당 클래스의 비공개 멤버에 액세스 @skypjack –

+0

@skypjack 예, 그게 전부입니다. 또 다른 방법은 개인적이고 액세스 할 수없는 클래스 이름 인 'A'가 (액세스 가능한) 전역 이름 'A'를 숨기는 것입니다. – Angew