2016-12-01 4 views
6

실수로 기본 구조체에 의해 파생 된 클래스의 개인 멤버가있는 (기본) 구조체의 일부 멤버 변수를 섀도 잉했습니다.컴파일러가 파생 클래스에서 숨겨진 기본 구조체의 멤버 변수에 대한 경고를 발생시켜야하지 않습니까?

구조체베이스 {
int a;
INT들 a :
}

파생 클래스 : 공공 민간 자료 {

... 비열한 버그의 원인이 내 경우에는 실수를했다

는 (다행히도 테스트 동안 붙 잡았다).
의도적으로 섀도 ​​잉 멤버가 (별로 나쁜 연습으로 간주되지 않는다면) 정말로 희소하다고 생각하기 때문에 컴파일러가 적어도 경고 (알맞은 섀도 잉이 허용되기 때문에 오류가 아닙니다)를 제기하지 않는 이유가 궁금합니다.

사용 된 컴파일러는 Microsoft Visual C++ 2015, 경고 수준 4입니다.
다른 컴파일러 (예 : GCC)가이 상황에 대한 특정 경고를 제공하는지 궁금합니다.

+0

gcc도 경고를 제공하지는 않지만 재미있는 점은이 동작이 다형성과 관련하여 전반적으로 어떻게 작용해야하는지입니다. – Starl1ght

+1

예 에서처럼 'private'가없는 경우에도 변수를 섀도 잉하는 것은 거의 항상 실수라고 생각합니다. [clang] (https://llvm.org/bugs/show_bug.cgi?id=31222)과 [gcc] (https://gcc.gnu.org/bugzilla/show_bug.cgi?)에 대한 기능 요청을 모두 제출했습니다. id = 78632). –

+1

@VittorioRomeo'Derived '가 쓰여질 때'Base'에'a'가 없다면 실수가 아닙니다. –

답변

4

섀도 잉이 좋지 않거나 잘 작동하는지 여부는 충돌하는 이름을 도입 한 순서에 따라 다릅니다. 이 경우

class DerivedA : public Base { 
private: 
    int a; 
}; 

:

은 클래스 라이브러리가 있다고 가정하고, 클래스 중 하나는 이것이다 :

struct Base { 
    int a; 
}; 

나중에, 클래스 라이브러리를 사용하는 고객 A는이 기록 음영 처리가 의도하지 않은 것일 수 있습니다. 고객이 실수로 Base::a을 (를) 음영 처리했습니다. 지금까지 너무 좋아

class DerivedB : public Base { 
private: 
    int b; 
}; 

:

그러나, 당신은 또한이 기록 고객 B를 있다고 가정합니다. 이제 라이브러리를 구축하여 Base 개체를 사용하고 고객 B는 라이브러리를 사용하여 BaseDerivedB 개체를 모두 사용하는 코드 본문을 작성합니다.

몇 주 후 새로운 기능을 사용하려면 Base에 새 회원을 추가해야한다는 것을 알고 있습니다.

struct Base { 
    int a; 
    int b; // new member variable 
}; 

이로 인해 라이브러리에 문제가 있습니까? 고객 B에게 문제가 발생합니까?

아니요, 문제가되지 않습니다.

BaseBase을 계속 사용할 것, 그것은 멋진 새 b 기능을 얻을 수있는 b 멤버를 사용할 수 있습니다 사용하는 코드의 모든

. DerivedB 개체가 Base이 필요한 함수로 전달 된 경우에도 Derived이 섀도 잉 b이라는 사실은 Base에 영향을 미치지 않습니다. Base을 사용하는 함수는 b이라고 말할 수 있으며 Base 멤버 변수에 액세스합니다.

한편, DerivedBDerivedB를 계속 사용합니다 사용하고, 그 코드가 b를 말할 때, 그것은 이전에 그랬던 것처럼, DerivedB::b를 얻을 고객 B의 모든 코드. 휴, 그림자가 그날을 구 했어요!

(물론 고객 B가 새로운 b 기능을 사용하기를 원한다면 고객 B는 충돌을 해결하기 위해 추가 작업을해야합니다.) 그러나 중요한 것은 섀도 잉이 새로운 문제를 생성하지 않는다는 것입니다 기존 코드에서)

섀도 잉이 좋은지 나쁜지간에 충돌이있는 이름을 도입 한 순서에 따라 달라집니다. 이것은 컴파일러가 이해할 수있는 것이 아닙니다.

+1

그래, 이건 컴파일러가 가지고있는 통찰력이 아니지만 컴파일러가 쉽게 경고 할 수있는 인간의 실수 일 수있다. 파생 클래스의 개발자가 섀도 잉을 의도하고 원하는 경우 경고를 무시하거나 억제 할 수 있습니다. 이 모든 경우에 원하지 않는 동작보다 더 많은 경고를 선호합니다 ... – roalz

+0

@roalz 그러나 라이브러리 작성자가 라이브러리 자체에 경고 억제를 어떻게 도입합니까? 경고는 고객 B의 코드에서 발생하며 라이브러리 작성자는 고객 B의 코드에 액세스 할 수 없습니다. –

+0

IMHO는 "고객"코드에 섀도 잉 (원하던가 아닌가)이 도입 되었기 때문에 경고를 표시하지 않을 수도 있습니다. 또는 나는 무엇인가 놓치고 있냐? – roalz