주요 개념은 클래스를 상속받는 하위 클래스에서 상위 클래스에 있는 비 가상함수를 재정의 하게되는 경우 생각하지 못한 동작이 발생할 수 있다는 부분을 설명해 준다.
코드 예시를 보자.
class Fruit
{
public:
void get();
...
};
class Apple : public Fruit {
...
};
위 코드를 바탕으로 아래처럼 구현 시 결과가 생각과 다를 수 있다.
Apple a;
Fruid *f = &a;
f->get(); // a 에 대한 포인터로 get을 호출한다.
// 위의 코드는 아래 코드처럼 동작하기를 기대하면서 작성되었다.
Apple *aa = &a;
aa->get();
// 하지만, Apple 에서 get을 다시 정의하는 경우 문제가 발생한다.
class Apple : public Fruit
{
public:
void get(); // Fruit의 get 함수를 가린다.
};
f->get(); // Fruit의 get을 호출
aa->get(); // Apple의 get을 호출
이런 결과가 나타나는 이유는 비 가상함수는 정적 바인딩으로 묶이기 때문에, 포인터 타입으로 호출 클래스 범위를 정의하기 때문이다.
반면, 가상함수는 동적 바인딩으로 묶이기 때문에 이를 재 정의 하려는 의도였다면 Fruit의 get을 virtual로 선언해서 다시 구현했어야 하는게 맞다.
어떤 용도가 되었건, 비가상 함수를 하위 클래스에서 다시 정의함으로써 호출 시 원하지 않는 결과를 얻지 않도록 해야한다는 게 이 내용의 핵심이니, 몸에 익혀두도록 하는게 좋겠다.
'C++' 카테고리의 다른 글
[C++/STL] vector의 크기, length 를 구하는 방법 (0) | 2021.11.29 |
---|---|
C++ 에서 구조체를 초기화 하는 여러가지 방법 (0) | 2021.07.29 |
[Effective C++] public 상속 모형은 반드시 "is-a" 를 따른다. (0) | 2021.06.05 |
[Effective C++] 내부에서 사용하는 객체에 대한 핸들은 반환하지 말자 (0) | 2021.06.02 |
[Effective C++] 변수의 정의는 최대한 늦추자 (0) | 2021.06.01 |