MSVC, Clang 및 GCC는이 코드에 동의하지 않습니다.
struct Base { int x; };
struct Der1 : public Base {};
struct Der2 : public Base {};
struct AllDer : public Der1, public Der2 {
void foo() {
Der1::Base::x = 5;
}
};
GCC :
<source>: In member function 'void AllDer::foo()':
<source>:10:21: error: 'Base' is an ambiguous base of 'AllDer'
10 | Der1::Base::x = 5;
| ^
Compiler returned: 1
Clang은 비슷한 오류를 제공하고 MSVC는 오류를 제공하지 않습니다.
여기 누구세요?
나는 이것이 [class.member.lookup]에 포함되어 있다고 생각 하지만,이 사건에 대해 무엇을 말하려고하는지 이해하는 데 어려움이 있습니다. 관련 부분을 인용하고 가능한 경우 일반 영어로 설명하십시오.
추신 :이 질문에서 영감을 얻은 이유 :: :: 연산자 trough 파생 클래스에서 기본 클래스에 대한 참조가 모호한 이유는 무엇입니까?
PPS : 실제로 내 의심은 Der1::Base
유형을 나타내는 지, Base
그리고 Der2::Base
정확히 동일한 유형인지 또는 하위 객체를 나타내는 지 여부입니다. 나는 그것이 첫 번째라고 확신하지만, 후자라면 MSVC가 옳을 것입니다.
답변
제목에 질문에 대답하기 위해, 예, Derived1::Base
참조합니다 주입-클래스 이름 [class.pre] Base
지금과는 않습니다 Derived2::Base
. 둘 다 클래스를 참조하십시오 ::Base
.
이제 정적 멤버 Base
가 있으면 조회 가 명확합니다. 하나만 있습니다.x
Base::x
이 예에서의 문제점은이 x
비 고정 부재이며 AllDer
갖는 두 이러한 부재. 멤버 가 하나만 x
있는 모호하지 않은 기본 클래스를 지정하여 이러한 액세스를 명확하게 할 수 있습니다 . 모호하지 않은 기본 클래스이며 멤버 가 하나 이므로 두 멤버 중 의미하는 것을 명확하게 지정합니다 . 멤버 도 하나 뿐이지 만의 모호한 기초는 아닙니다 . 의 모든 인스턴스 에는 유형의 하위 객체가 두 개 있습니다. 따라서 귀하의 예에서는 모호합니다. 그리고 또 다른 이름 이기 때문에AllDer
x
Derived1
x
Derived1::x
x
AllDer
Base
x
AllDer
AllDer
Base
Base::x
Derived1::Base
Base
모호합니다.
[class.member.lookup] x
은 nested-name-specifier의 컨텍스트에서 조회되도록 지정하므로 먼저 해결해야합니다. 우리는 참으로 찾고 있습니다 Base::x
하지, Derived1::x
우리가 해결하여 시작했기 때문에, Derived1::Base
로 Base
. 이 부분은 단 하나있다, 성공 x
의 Base.
주 (12)가 명시 적으로 명확한 이름 조회를 사용하여 아직도 그 같은 이름을 가진 여러 하위 객체가있을 때 실패 할 수 있음을 알려줍니다 [class.member.lookup]에. D::i
이 예에서 기본적으로 당신 Base::x
입니다.
답변
클래스 이름을 클래스의 멤버로 참조 할 수있는 이유는 cpp using Base = ::Base;
가 Base에 작성한 것처럼 편리하게 사용할 수 있도록 cpp의 별칭을 지정하기 때문 입니다.
직면 한 문제 Der1::Base
는 Base
입니다.
따라서 쓸 때 Der1::Base::x
와 동일합니다 Base::x
.