[ Effective C++ ] 항목 33 : 상속된 이름을 숨기는 일은 피하자

Minsu._.Lighting·2023년 12월 8일
0

[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "

[핵심]

" 상속 관계에서의 데이터 멤버, 멤버 함수의 유효범위에 따른 동작을 생각하며 구성하자! "

  • 파생 클래스의 이름은 기본 클래스의 이름을 가린다!
  • public 상속에서 이름 가림 현상은 바람직하지 않다!
  • 가려진 이름을 다시 볼 수 있게 하는 방법으로는 using선언 혹은 전달 함수를 쓰면 된다!

💡 C++의 유효범위(scope)

int x;

void someFunc()
{
	double x;
    
    cin >> x;
}
  • 안쪽 유효범위의 이름이 바깥쪽 유효범위의 이름을 가린다
    - 컴파일러는 x라는 이름을 만나면 자신이 현재 처리하고 있는 유효범위에서 x를 찾는다
    (찾으면 탐색 종료, 찾지 못하면 전역 범위에 닿을때까지 바깥 유효범위에서 계속 탐색 반복)
    - 이 때 x의 자료형이 무엇인지는 중요하지 않다!


💡 상속 관계에서도 마찬가지

📌 예시 1

class Base
{
private:
	int x;
    
public:
	virtual void mf1() = 0;
    virtual void mf2();
    void mf3();
    ...
};

class Derived : public Base
{
public:
	virtual void mf1();
    void mf4();
    ...
};

void Derived::mf4()
{
	...
    mf2();
    ...
}
  • mf4()함수의 동작 방식

📌 상속 관계에서 함수 오버로드 시

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();		// Derived::mf1 호출
d.mf1(x);		// Derived::mf1이 Base::mf1을 가린다

d.mf2();		// Basse::mf2 호출

d.mf3();		// Derived::mf3 호출
d.mf3(x);		// Derived::mf3이 Base::mf3을 가린다
  • 이름이 같은 함수들이 받아들이는 매개변수 타입이 같거나 다르거나 상관 없고, 심지어 가상 함수인지 비가상 함수인지의 여부도 상관없이 이름이 가려진다
    - 파생 클래스를 새로 정의할 때 멀리 떨어져 있는 기본 클래스로부터 오버로드 버전을 상속 시키는 경우를 막기 위함

📌 using 선언을 이용해 가려진 이름을 사용하자!

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:
	using Base::mf1;
    using Base::mf3;
    
	virtual void mf1();
    void mf3();
    void mf4();
    ...
};
  • 기본 클래스로부터 상속을 받으려 할 때 오버로드된 함수가 있고, 이 함수들 중 몇 개만 재정의 하고 싶다면 각 이름에 대해 using 선언을 붙여주자

📌 기본 클래스가 가진 함수를 전부 상속하고 싶진 않을 때

class Base
{
public:
	virtual void mf1() = 0;
    virtual void mf1(int);
    ...
};

class Derived : private Base
{
public:
	virtual void mf1()
    { Base::mf1(); }
    ...
};
  • using 선언으로는 해결 불가
    - using 선언 시 그 이름에 해당하는 것들이 모두 파생 클래스로 내려가기 때문

  • private 상속과 간단한 전달 함수를 만들자
    - [ 항목 39 : private 상속은 심사숙고해서 구사하자 ] 참조
    - 전달 함수는 using 선언을 사용하지 못하는 컴파일러에서 우회적으로 해결하기 위해서도 사용

profile
오코완~😤😤

0개의 댓글

관련 채용 정보