스토리텔링 개발자

[Effective C++] 36. 상속된 비가상 함수 이름 가리기 문제 본문

개발/Effective C++

[Effective C++] 36. 상속된 비가상 함수 이름 가리기 문제

김디트 2024. 7. 5. 09:23
728x90

항목 36. 상속받은 비가상 함수를 파생클래스에서 재정의하는 것은 금물

 

 

 

비가상 함수를 가리면 생기는 문제
class B
{
public:
    void mf();
    ...
};

class D : public B
{
public:
    void mf(); // B::mf를 가려버린다!
    ...
};

D x; // D 타입
B* pB = &x; // x에 대한 포인터를 B*에 넣는다.
D* pD = &x; // x에 대한 포인터를 D*에 넣는다.

pB->mf(); // B::mf를 호출
pD->mf(); // D::mf를 호출!!!!
  • 비가상 함수를 가려버리면, 포인터가 어디에 담겨있느냐에 따라 다르게 동작한다.
    • 가상 함수 및 오버라이드를 사용했을 경우 발생하지 않는 문제이다.

 

 

문제 동작 이유
  • 비가상 함수는 정적 바인딩으로 묶이기 때문이다. (항목 37 참조)
    • pB는 'B에 대한 포인터' 타입으로 선언되었기 때문에, pB를 통해 호출되는 비가상 함수는 항상 B 클래스에 정의되어 있을 것이라고 결정해 버린다는 의미이다.
  • 반면, 가상 함수는 동적 바인딩으로 묶인다. (항목 37 참조)
    • 가상 테이블을 통해 올바른 클래스를 동적으로 찾아갈 수 있다.
  • 그러므로 재정의를 해야 하는 상황이라면 반드시 가상 함수 오버라이드를 택하도록 하자.

 

 

 

가상 소멸자 문제
  • 항목 7의 가상 소멸자 관련 문제는 사실 이번에 살펴본 문제의 특수한 경우라고 할 수 있다.
  • 항목 5에서 봤듯, 컴파일러가 알아서 소멸자를 만들게 되면, 그야말로 비가상 함수를 가리는 상황이 되기 때문이다.
728x90
Comments