Effective C++에 있는 내용이라고 겁먹지 말자. 우리는 이미 이 내용을 제가 C++ 포스팅 하면서 언급을 한 적이 있습니다. 왜 다형성을 가진 기본 클래스에서는 소멸자를 가상 소멸자로 써야 하는가? 우선 다형성과 그 이유에 대해서 먼저 보시죠.
위 두 포스팅만 보더라도 왜 가상 소멸자를 쓰는지 이유는 충분히 알 수 있을 것입니다. 가상 함수를 C++에서 구현하려면 클래스에 별도의 자료구조가 하나 들어가야 합니다. 이 자료구조는 프로그램 실행 중에 주어진 객체에 대해 어떤 가상 함수를 호출해야 하는지는 결정하는 데 쓰이는 정보인데, 실제로는 포인터의 형태를 취하는 것이 대부분이고, 이를 가상 함수 테이블 포인터(Virtual table pointer) 즉, vptr이라는 이름으로 부릅니다. vptr은 가상 함수의 주소, 포인터들의 배열을 가리키고 있으며 가상 함수 테이블 포인터의 배열은 가상 함수 테이블(virtual table). vtbl이라고 부릅니다. 가상 함수를 하나라도 갖고 있는 클래스는 반드시 그와 관련된 vtbl을 갖고 있습니다. 어떤 객체에 대해 어떤 가상 함수가 호출되려고 하면, 호출되는 실제 함수는 그 객체의 vptr이 가리키는 vtbl에 따라 결정이 됩니다. vtbl에 있는 함수 포인터들 중 적절한 것이 연결된다는 의미이죠.
지금까지 가상 소멸자에 대해서만 이야기 했는데, 순수 가장 소멸자(pure virtual destructor)는 어떨까요? 순수 가상 함수는 해당 클래스를 추상 클래스(abstract class)로 만듭니다. 하지만 어떤 클래스가 추상 클래스였으면 좋겠는데 마땅히 넣을 만한 순수 가상 함수가 없을 때도 생기게 마련인데요. 이럴 때에는 어떻게 할까요?
추상클래스는 본래 기본 클래스로 쓰일 목적으로 만들어진 것이고, 기본 클래스로 쓰이려는 클래스는 가상 소멸자를 가져야 합니다. 한편 순수 가상 함수가 있으면 바로 추상 클래스가 되죠. 따라서, 추상 클래스로 만들고 싶은 클래스에 순수 가상 소멸자를 선언하는 것입니다.
모든 기본 클래스가 다형성을 갖도록 설계된 것은 아닙니다. 예를 들어 표준 string 타입이나 STL 컨테이너 타입은 기본 클래스는 커녕 다형성의 흔적조차 없기 때문이죠. 한편, 기본 클래스로는 쓰일 수 있지만 다형성은 갖지 않도록 설계된 클래스도 있는데 이런 클래스에서 이들에게서 가상 소멸자를 볼 수 없는 것은 기본 클래스의 인터페이스를 통한 파생 클래스 객체의 조작이 허용되지 않기 때문이죠.
* 다형성을 가진 기본 클래스에는 반드시 가상 소멸자를 선언해야 합니다. 즉, 어떤 클래스가 가상 함수를 하나라도 갖고 있으면, 이 클래스의 소멸자도 가상 소멸자이어야 합니다.
* 기본 클래스로 설계되지 않았거나 다형성을 갖도록 설계되지 않은 클래스에는 가상 소멸자를 선언하지 말아야 합니다.
'Effective C++' 카테고리의 다른 글
항목 9. 객체 생성 및 소멸 과정중에는 절대 가상 함수를 호출하지 말자!!! (0) | 2010.10.06 |
---|---|
항목 8. 예외가 소멸자를 떠나지 못하도록 붙들어 놓자 (0) | 2010.10.05 |
[EC++] 항목 6. 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자 (0) | 2010.09.15 |
[EC++] 항목 5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자 (0) | 2010.09.14 |
[EC++] 항목 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자 (0) | 2010.09.10 |