복사 생성자에서 C ++ 네임 스페이스 충돌

다음 코드가 있습니다.

namespace A {
    struct Foo {
        int a;
    };
}

struct Foo {
    int b;
};

struct Bar : public A::Foo {
    Bar(Foo foo) {
        c = foo.b;
    }
    int c;
};

A :: Foo에는 b라는 멤버가 없으므로 C ++ 컴파일러는 “c = foo.b”에서 불평합니다. :: Foo로 Bar 매개 변수의 유형을 변경하면 작동합니다.

내 질문은이 동작의 합리적인 이유입니다 (상속이 Bar가 A 네임 스페이스에 들어가게한다는 사실과 관련이 있다고 생각하지만이 이론을 뒷받침하는 문서를 찾을 수는 없습니다.



답변

모든 수업은 회원으로 이름이 주입되어 있습니다. 이름을 지정할 수 있습니다 A::Foo::Foo. 이것을 주입 된 클래스 이름이라고합니다.

[수업]

2 class-name은 class-name이 표시된 직후 선언되는 범위에 삽입됩니다. class-name은 클래스 자체의 범위에도 삽입됩니다. 이것을 injection-class-name이라고합니다. 액세스 확인을 위해 주입 된 클래스 이름은 마치 공용 멤버 이름 인 것처럼 처리됩니다.

[basic.lookup]

3 클래스의 삽입 클래스 이름은 이름 숨기기 및 조회를 위해 해당 클래스의 멤버로 간주됩니다.

인수 유형의 규정되지 않은 이름 검색은 클래스의 범위에서 시작 Bar하므로 해당 클래스의 멤버를 설명하기 위해 기본 클래스의 범위로 계속 진행됩니다. 그리고 A::Foo::Foo유형 이름으로 찾을 수 있습니다.

글로벌 유형 이름을 사용하려면 주변 (글로벌) 네임 스페이스로 이름을 규정하십시오.

Bar(::Foo foo) {
    c = foo.b;
}

주입 된 클래스 이름이 표시되지 않는 범위에서 정규화 된 조회를 수행하는 것입니다.

후속 “이유”질문에 대해서는


답변

완전한 답변 Bar은 아니며 ( 컴파일 이후)를 입력하지 않는 코드 만 표시 합니다 namespace A. 상속 할 때 A::Foo1모호함에 대한 문제는 없음을 알 수 있습니다.Foo 이 다른 수 Bar있습니다 A.

namespace A {
    struct Foo {
        int a;
    };

    struct Foo1 {
        int a;
    };
}

struct Foo {
    int b;
};

struct Bar : public A::Foo1 {
    Bar(Foo foo) {
        c = foo.b;
    }
    int c;
};


답변