다형성 가진 기본 클래스의 가상 소멸자(effective c++ 07)

2015. 8. 2. 17:32프로그래밍/Effective C++

728x90
728x90

비가상 소멸자

상속 관계에서 소멸자에 virtual 키워드를 붙이지 않게 되면 의도치 않은 결과가 나오게 된다. 


문제점
파생 클래스 객체에 대한 포인터가 가리키는 객체가 삭제될 때는 기본 클래스 포인터를 통해 삭제된다.
C++의 규정에 의하면, 기본 클래스 포인터를 통해 파생 클래스 객체가 삭제될 때 그 기본 클래스에 
비가상 소멸자가 들어 있으면 프로그램 동작은 미정의 사항이다.
대개 그 객체의 파생 클래스 부분이 소멸되지 않게 된다.
기본 클래스 부분은 소멸 과정이 일어나고 파생 클래스는 소멸이 일어나지 않기 때문에 
부분 소멸(partially destroyed) 객체가 된다.

무조건 virtual을 붙이면 안된다.
클래스 내부에 가상 함수가 하나도 없는 클래스의 소멸자를 virtual로 선언하면 용량의 낭비가 일어난다.

문제점
클래스에 virtual 키워드가 붙게 되면 가상 함수 테이블 포인터( virtual table pointer )가 생기고, 
이 포인터는 32bit 운영체제에서는 4byte, 64bit 운영체제에서는 8byte의 크기를 갖는다.
그렇기 때문에 가상 함수가 없는 클래스에 virtual 키워드를 붙이게 되면 쓸데없이 용량이 커지게 되는 결과가 나온다.

가상 함수가 하나라도 있는 클래스에만 가상 소멸자를 선언하자.

STL 컨테이너 상속 금지
STL 컨테이너의 소멸자는 비가상 소멸자 이다.
STL 컨테이너 타입(vector, list, set, tr1::unordered_map 등등 )은 기본적으로 비가상 소멸자로 이루어져 있기 때문에, 
STL 컨테이너 타입을 상속받아 자신만의 클래스를 만들려고 하면 어떻게 동작할 지 알 수 없다.

순수 가상 소멸자 쓰기
순수 가상 함수는 해당 클래스를 추상 클래스( abstract class )로 만들게 되고 순수 가상 함수를 재정의하지 않았을 경우 그 자체로 인스턴스를 못하기 때문에 소멸자를 순수 가상 소멸자로 선언하게 되면 위의 문제를 미리 방지 할 수 있다.

이것만은 잊지 말자
다형성을 가진 기본 클래스에는 반드시 가상 소멸자를 선언해야 한다.
즉, 어떤 클래스가 가상 함수를 하나라도 갖고 있으면, 이 클래스의 소멸자도 가상 소멸자여야 한다.

기본 클래스로 설계되지 않았거나 다형성을 갖도록 설계되지 않은 클래스에는 가상 소멸자를 선언하지 말아야 한다.



728x90
반응형