KoreanFoodie's Study

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

Tutorials/C++ : Advanced

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

GoldGiver 2022. 10. 25. 16:27

C++ 프로그래머의 필독서이자 바이블인, 스콧 마이어스의 Modern Effective C++ 를 읽고 기억할 내용을 요약하고 있습니다. 꼭 읽어보시길 추천드립니다!

항목 33 : 상속된 이름을 숨기는 일은 피하자

핵심 :

1. 파생 클래스의 이름은 기본 클래스의 이름을 가린다. public 상속에서는 이런 이름 가림 현상은 바람직하지 않다.
2. 가려진 이름을 다시 볼 수 있게 하는 방법으로, 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:
	virtual void mf1();
	void mf3();
	void mf4();
};

...

Derived d;
int x;

d.mf1(); // Derived::mf1 호출
d.mf1(x); // 에러! Derived::mf1 이 Base::mf1 을 가림

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

d.mf3(); // Derived::mf3 호출
d.mf3(x); // 에러! Derived::mf3 이 Base::mf3 을 가림

해당 함수가 어떤 인자를 받는지, 가상 함수인지 아닌지와 상관없이, 파생 클래스에서 이름이 같은 함수는 기반 클래스의 함수를 가리게 된다. 이는 멀리 떨어져 있는 기본 클래스로부터 오버로드 버전을 상속시키는 경우를 막기 위한 의도이다. Derived 클래스에 다음 두 줄을 추가하면, 위의 코드의 에러를 해결할 수 있다.

class Derived: public Base
{
public:
	// Base 에 있는 것들 중 mf1 과 mf3 를 이름으로 가진
	// 것들을 Derived 의 유효범위에서 볼 수 있도록 만듦
	using Base::mf1;
	using Base::mf3;

	virtual void mf1();
	void mf3();
	void mf4();
};

...

Derived d;
int x;

d.mf1(x); // Base::mf1 호출
d.mf3(x); // Base::mf3 호출

 

그렇다면 이제 한 걸음 더 나아가보자. int 인자를 받는 mf1 함수와 인자를 받지 않는 mf1 함수가 Base 클래스에 정의되어 있고, Derived 클래스는 mf1 을 찾을 때 인자를 받지 않는 mf1 함수만 탐색하게 만들고 싶다고 하자. 이 경우, 전달 함수(forwarding function) 을 만들어 주면 이 문제를 간단히 해결할 수 있다.

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

class Derived: private Base
{
public:
	// 암시적으로 인라인 함수가 됨
	virtual void mf1()
	{
		Base::mf1();
	}
};

...

Derived d;
int x;

d.mf1(); // Derived::mf1 호출 (매개변수 없는 버전)
d.mf1(x); // 에러! Base::mf1() 은 가려져 있음

 

Comments