[Effective C++] Item 9: 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자
Item 9: 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자
말 그대로 객체 생성 및 소멸 과정에서는 가상 함수를 호출하지 말아야 한다.
책에서 보여주는 예제의 흐름에서 가장 문제가 되는 부분인 기본 클래스의 생성자가 호출될 동안에는, 가상 함수는 절대로 파생 클래스 쪽으로 내려가지 않는다. 그 대신, 객체 자신이 기본 클래스 타입인 것처럼 동작한다. 즉, 생성 과정에서는 가상 함수가 먹히지 않는다.
사실 생성자의 흐름으로 본다면 말이 안되는게 맞다.
기본 클래스 생성자는 파생 클래스 생성자보다 앞서서 실행되기 때문에, 기본 클래스 생성자가 돌아가고 있을 시점에 파생 클래스 데이터 멤버는 아직 초기화된 상태가 아니라는 것이 핵심이다. 이는 미정의 동작을 불러올 수 있다.
파생 클래스 객체의 기본 클래스 부분이 생성되는 동안은, 그 객체의 타입은 바로 기본 클래스이다. 호출되는 가상 함수는 모두 기본 클래스의 것으로 결정될 뿐만 아니라, 런타임 타입 정보를 사용하는 언어 요소를 사용한다고 해도 이 순간엔 모두 기본 클래스 타입의 객체로 취급한다.
객체가 소멸될 때도 마찬가지로 파생 클래스의 소멸자가 실행되고 나면 파생 클래스만의 데이터 멤버는 정의되지 않은 값으로 가정하기 때문에, C++은 이들이 없다고 취급하고 진행한다.
생성자안에 존재하는 가상함수는 적은 수라면 눈에 쉽게 보일 수 있지만, 생성자가 복잡해지면 이런 문제를 찾아내기가 어렵다.
이러한 문제를 해결하기 위해서는 가상함수를 비가상 멤버 함수로 교체하는 것이다. 필요한 정보는 멤버 변수에 저장하고, 생성자에서 초기화하고, 소멸자에서 정리하면 된다.
정리
- 생성자 혹은 소멸자 안에서 가상 함수를 호출하지 말자. 가상 함수라고 해도, 지금 실행중인 생성자나 소멸자에 해당되는 클래스의 파생 클래스 쪽으로는 내려가지 않는다.
댓글남기기