[Effective C++] Item 7: 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자
Item 7: 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자
C++의 규정에 의하면, 기본 클래스 포인터를 통해 파생 클래스 객체가 삭제될 때 그 기본 클래스에 비가상 소멸자가 들어 있으면 프로그램 동작은 미정의 사항이라고 한다. 대개는 그 객체의 파생 클래스 부분이 소멸되지 않게 된다.
이러한 문제를 해결하기 위해선 기본 클래스에 가상 소멸자를 넣어서 파생 클래스 객체를 기본 클래스 포인터로 삭제할 때 원하는 방향을 지정할 수 있다. 기본 클래스의 소멸자 앞에 virtual
키워드를 붙임으로 객체가 전부 소멸된다. (파생까지)
이 개념을 좀 더 넓게 이해하기 위해선 가상 함수의 개념을 깊게 이해하는 것이 중요하다.
가상 함수 테이블이라는 명칭으로 실제로 메모리에 할당될 때, 추가로 vptr이라는 포인터가 추가로 할당된다. 이 포인터는 가상 함수 테이블을 가리키는 포인터로, 이를 통해 가상 함수를 호출할 때마다 해당 함수의 주소를 찾아가게 된다. 즉, 가상 함수를 하나라도 갖고 있는 클래스는 반드시 그와 관련된 가상 함수 테이블을 가지게 된다.
실제로 호출되려 하면 실제 함수는 그 객체의 vptr이 가리키는 vtbl에 따라 결정된다.
어느 경우를 막론하고 소멸자를 전부 virtual로 선언하는 것은 virtual로 절대 선언하지 않는 것만큼이나 편찮은 마인드다. 가상 소멸자를 선언하는 것은 그 클래스에 가상 함수가 하나라도 들어있는 경우에만 한정하자.
가상 함수가 전혀 없는데도 비가상 소멸자 때문에 어려움을 겪는 경우도 종종 있다. string
타입의 가상 함수를 갖고 있지 않지만 전후 사정 무시하고 이 타입을 기본 클래스로 잡아버리는 경우가 있기 때문이다.
추가로 기본 클래스에 가상 소멸자를 넣자는 규칙은 다형성을 가진 기본 클래스에만 해당된다. 모든 클래스가 다형성을 가지도록 설계된 것은 아니기에 이를 잘 구분하고 사용하자.
정리
- 다형성을 가진 기본 클래스에는 반드시 가상 소멸자를 선언해야 한다. 즉, 어떤 클래스가 가상 함수를 하나라도 갖고 있으면, 이 클래스의 소멸자도 가상 소멸자이어야 한다.
- 기본 클래스로 설계되지 않았거나 다형성을 갖도록 설계되지 않은 클래스에는 가상 소멸자를 선언하지 말아야 한다.
댓글남기기