[Effective C++] 36. 상속받은 비가상 함수를 파생 클래스에서 재정의하는 것은 절대 금물!
728x90
반응형
결론부터 얘기하면, 상속받은 비가상 함수를 파생 클래스에서 재정의 하지 말자는 것이다.
상속받은 비가상 함수를 파생 클래스에서 재정의한 아래의 예시를 보자.
class B
{
public:
void mf();
...
};
class D: public B
{
public:
void mf();
...
};
---
D x;
B *pB = &x;
pB->mf(); // B::mf()를 호출
D *pD = &x;
pD->mf(); // D::mf()를 호출
이렇게 두 가지 동작을 하게 되는 이유는 B::mf 및 D::mf 등의 비가상 함수는 정적 바인딩(static binding)으로 묶이기 때문이다.
즉, pB는 'B에 대한 포인터' 타입으로 선언되었기 때문에 pB를 통해 호출되는 비가상 함수는 항상 B 클래스에 정의되어 있을 것이라고 결정한다는 말이다. 이건 B에서 파생된 객체를 pB가 가리키고 있다고 해도 위처럼 마찬가지의 동작을 한다.
반면, 가상 함수의 경우엔 동적 바인딩(dynamically binding)으로 묶인다. 만약 mf 함수가 가상 함수였다면 mf가 pB에서 호출되나 pD에서 호출되나 D::mf가 호출된다. pB 및 pD가 진짜로 가리키는 대상은 D타입의 객체이기 때문이다.
항목 32에서 public 상속의 의미는 "is-a(.. 는.. 의 일종이다)"이다. 그리고 항목 34에서 비가상 멤버 함수는 클래스 파생에 관계없는 불변 동작을 정해두는 거라고 이야기했었다. 이 두 가지 포인트를 B, D 클래스 및 비가상 멤버 함수인 B::mf에 그대로 가져가면 이렇게 풀 수 있다.
- B 객체에 해당되는 모든 것들이 D 객체에 그대로 적용된다. 왜냐면 모든 D 객체는 B 객체의 일종이기 때문이다.
- B에서 파생된 클래스는 mf 함수의 인터페이스와 구현을 모두 물려받게 된다. mf는 B 클래스에서 비가상 멤버 함수이기 때문이다.
여기서 D에서 mf를 재정의하는 순간 설계에 모순이 생긴다.
결과적으로 어떤 상황에서도 상속받은 비가상 함수를 재정의 하는 것은 절대 금물이다.
요약
- 상속받은 비가상 함수를 재정의하는 일은 절대로 하지 말자.
728x90
반응형
'Books > Effective C++' 카테고리의 다른 글
[Effective C++] 38. "has-a(..는..를 가짐)" 혹은 "is-implemented-in-terms-of(..는..를 써서 구현됨)"를 모형화할 때는 객체 합성을 사용하자 (0) | 2022.07.03 |
---|---|
[Effective C++] 37. 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자 (0) | 2022.07.02 |
[Effective C++] 35. 가상 함수 대신 쓸 것들도 생각해 두는 자세를 시시때때로 길러 두자 (0) | 2022.06.26 |
[Effecitve C++] 34. 인터페이스 상속과 구현 상속의 차이를 제대로 파악하고 구별하자 (0) | 2022.06.25 |
[Effective C++] 33. 상속된 이름을 숨기는 일은 피하자 (0) | 2022.06.25 |
댓글
이 글 공유하기
다른 글
-
[Effective C++] 38. "has-a(..는..를 가짐)" 혹은 "is-implemented-in-terms-of(..는..를 써서 구현됨)"를 모형화할 때는 객체 합성을 사용하자
[Effective C++] 38. "has-a(..는..를 가짐)" 혹은 "is-implemented-in-terms-of(..는..를 써서 구현됨)"를 모형화할 때는 객체 합성을 사용하자
2022.07.03 -
[Effective C++] 37. 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자
[Effective C++] 37. 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자
2022.07.02 -
[Effective C++] 35. 가상 함수 대신 쓸 것들도 생각해 두는 자세를 시시때때로 길러 두자
[Effective C++] 35. 가상 함수 대신 쓸 것들도 생각해 두는 자세를 시시때때로 길러 두자
2022.06.26 -
[Effecitve C++] 34. 인터페이스 상속과 구현 상속의 차이를 제대로 파악하고 구별하자
[Effecitve C++] 34. 인터페이스 상속과 구현 상속의 차이를 제대로 파악하고 구별하자
2022.06.25