Effective C++/Effective C++
[Effective C++] 33. 상속된 이름 가리기 문제
김디트
2024. 7. 2. 14:06
728x90
항목 33. 상속된 이름을 숨기는 일은 피하자
상속과 유효범위
- 상속 역시 유효범위로 취급한다.
- 유효범위 내에서 이름을 찾지 못하면 상위 유효범위를 탐색한다.
C++ 이름 가리기 규칙
- c++의 이름 가리기 규칙은 단지 이름만으로 유효범위를 탐색하고, 가려버린다.
- 그렇기에 아래와 같은 문제가 발생할 수 있다.
class Base
{
private:
int x;
public
virtual void mf1() = 0;
virtual void mf1(int);
virtual void mf2();
void mf3();
void mf3(double);
...
};
class Derived : public Base
{
public:
virtual void mf1();
void mf3();
void mf4();
...
};
Derived d;
int x;
...
d.mf1(); // 컴파일 성공
d.mf1(x); // 에러! Derived::mf1이 Base::mf1을 가려서 찾을 수 없다.
d.mf2(); // 컴파일 성공
d.mf3(); // 컴파일 성공
d.mf3(x); // 에러! Derived:mf3이 Base::mf3을 가려서 찾을 수 없다.
- 함수의 매개변수, 리턴값, 심지어 가상 비가상 여부조차 가리지 않고 이름을 가려버린다.
상속 시 이름가리기 규칙의 의미
- 어떤 라이브러리나 프레임워크로 파생 클래스를 만들 때, 멀리 떨어진 기본 클래스로부터 오버로드 버전을 상속받아 버리는 경우를 실수로 간주하겠다는 의도일 것이다.
- 허나 오버로드 버전을 상속하고 싶은 경우가 너무나 많은 문제가 있다.
가려진 이름 꺼내기
- 가려진 이름은 using 선언으로 끄집어낼 수 있다.
class Base
{
public:
virtual void mf1() = 0;
virtual void mf1(int);
void mf3();
void mf3(double);
}
class Derived : public Base
{
public:
using Base::mf1;
using Base::mf3;
// 유효 범위 내에서 볼 수 있도록 using 처리
virtual void mf1();
void mf3();
};
- using 기법으로는, 기본 클래스가 가진 함수 중 일부만 상속하고 싶은 경우에 대한 처리가 불가능하다.
- 전달 함수를 정의하여 해결한다.
- using을 지원하지 않는 컴파일러에서도 유용할 것이다.
class Base
{
public:
virtual void mf1() = 0;
virtual void mf1(int);
...
}
class Derived : private Base // private 상속이므로 각 public 부모 함수들은 private화
{
public:
virtual void mf1() { Base::mf1(); } // 전달 함수로 처리한다.
...
};
- 템플릿 클래스 상속과 엮일 경우 다른 문제가 발생한다.(항목 43 참조)
728x90