[C++] 상속받은 비가상 함수의 재정의는 절대 금물!!


앞선 포스팅에서 언급했듯이

비가상 함수의 상속은 파생에 관계없는

불변동작을 정해두는 것이다.

인터페이스와 필수 구현을 물려주는 것

그 것이 바로 비가상 함수의 상속인 것이다.




양쪽에서 x의 객체로 부터 mf 함수를 호출한다.

함수도 똑같고 객체도 똑같으니, 동작 또한 같다.

하지만 D클래스가 mf 함수를 또 정의하면 어떻게 될까.





이렇게 두 개의 다른 동작이 나오는 이유는

비가상 함수는 정적 바인딩이기 때문이다.

pb는 B에 대한 포인터 타입으로 선언되었기 때문에

pb를 통해 호출되는 비가상 함수는 항상 B클래스에

정의되어 있을 것이라고 결정해 버린다.


마찬가지로 B에서 파생된 객체를 pb가

가리키고 있다 해도 결과는 마찬가지이다.




반면, 가상 함수는 동적바인딩으로 묶이는데

mf가 가상 함수 였다면, mf가 어디서

호출 되든 D::mf가 호출된다.

pb, pd가 진짜로 가리키는 대상은 D 타입 객체이기 때문이다.




즉, 비가상 함수의 상속에서는

B냐 D냐를 결정하는 요인이 해당 객체가 아니라

그 객체를 가리키는 포인터 타입이라는 것이다.




이제는 비가상 함수의 재정의를 하면 안되는

이론적인 이유에 대해서 알아보도록 하자.


비가상 멤버 함수는 클래스 파생에 관계없는

불변동작을 정해두는 것이다.

is-a 관계 상속(public)의 관점에서 보자면




1. B 객체에 해당되는 모든 것들이 D 객체에 그대로 적용된다.

2. B에서 파생된 클래스는 mf 함수의 인터페이스와 구현을 모두 물려받는다.


D에서 mf를 재정의 하는 순간 이러한 설계는 모순이 생겨 버린다.

B의 mf 구현을 모든 파생 클래스에서 사용하도록 정한 것인데

mf를 D에서 재정의 하는 순간 모든 D는 B의 일종이라는

명제는 사라져 버린다. D에서 정말 mf함수를 다르게

구현해야 한다면 비가상 함수가 아닌 가상 함수여야 한다.



POINT!!

상속받은 비가상 함수를 재정의하는 일은 절대로 하지 말자!!



+ Recent posts