항목 36. 상속받은 비가상 함수를 파생 클래스에서 재정의하는 것은 절대 금물!
1. 바인딩 : 프로그램 소스에 쓰인 각종 내부 요소, 이름, 식별자들에 대해 값 혹은 속성을 확정하는 과정을 일컫는다.
빌드중에 이과정이 일어나면 정적바인딩, 실행중에 일어나면 동적바인딩
c++에서 가상함수 바인딩은 문서상으로 동적바인딩이나, 실제로는 런타임 성능을 높익기 위해 정적 바인딩을 쓴다.
컴파일 중에 가상함수테이블을 파생 클래스에 맞게 바꿈으로서 정적바인딩처럼!
ex) "int foo = 2;" 일때 데이터타입이 int인것과 변수명이 foo로 정해지는게 정적바인딩이고 foo 변수에 2가대입되는게 동적바인딩이다!
lass B{
public :
void mf(); // 비가상함수
};
class D : public B{
public :
void mf(); //비가상함수 재정의
};
B *pB = new D();
D *pD = new D();
pB->mf(); // B::mf()가 호출
pD->mf(); // D::mf()가 호출
비가상함수를 위와 같이 호출시 호출한 객체의 타입으로 묶인 mf()가 호출된다.
가상함수 호출시 호출객체가 가리키는 타입의 mf()가 호출된다.
2. 비가상함수를 파생클래스에서 재정의하면 안되는 이유
1) D는 B의 일종이다라는 명제(public 상속)를 참이라는 가정하에, D는 mf()를 B와 다르게 구현하고싶어하고, B포함 B파생클래스로부터 만들어진객체가 B의 mf()를 사용해야한다고 가정한다면, D is B 명제가 거짓이되므로 모순이다. 이때는 public 상속금지이다.
2) D는 B로부터 상속받을수밖에 없는 이장이라면, 그리고 D에서 B와 다르게 구현해야한다면, "mf는 클래스 파생에 상관없이 B에 불변동작을 나타낸다"라는 명제가 거짓이된다. 이때는 가상함수사용필요하다.
3) 만약 모든 D가 B의 일종이고 mf가 B에 대해 불변동작을 보여야한다면, 재정의 자체를 생각하는게 문제다.
이것만은 알아두자!
상속받은 비가상함수를 재정의 하지 말자!