Post
다형성을 가진 기본 클래스에서 비가상 소멸자를 통해 소멸하면 어떻게 될까?
class TimeKeeper {
public:
TimeKeeper();
~TimeKeeper();
...
};
TimeKeeper* getTimeKeeper();
TimeKeeper *ptk = getTimeKeeper();
...
delete ptk;
기본 클래스 포인터를 통해 파생 클래스 객체가 삭제될 때 비가상 소멸자가 들어 있으면, 대부분 그 객체의 파생 클래스 부분이 소멸되지않게 된다.
파생 클래스의 소멸자도 실행되지 않지만 기본클래스 부분은 소멸 과정이 제대로 끝나 '부분소멸'이 되게된다.
이 문제를 없애기위해서는 기본 클래스에 가상 소멸자를 넣어놓으면된다.
class TimeKeeper {
public:
TimeKeeper();
virtual ~TimeKeeper();
...
};
TimeKeeper* getTimeKeeper();
TimeKeeper *ptk = getTimeKeeper();
...
delete ptk;
소멸자 앞에 virtual 만 붙여줄 뿐인데, 파생 클래스 까지 객체 전부가 소멸된다.
하지만 기본클래스로 설계되지 않거나 다형성을 갖도록 설계되지않은 클래스조차 마구잡이로 가상소멸자를 선언하면 안된다.
class Point {
public:
Point (int xCoord, int yCoord);
~Point();
private:
int x,y;
};
위와같은 코드가 있을때, Point객체는 int가 2개 있으니 64bit를 생각하면 64bit레지스터에 맞게된다.
하지만 Point 클래스의 소멸자가 가상 소멸자라면 64bit가 아닌 96bit가 된다.(C++에서는 가상함수를 구현하기 위해 클래스에 별도로 가상 함수 테이블 포인터 라는 자료구조가 들어가야하기 때문이다.)
그리고 다른 언어로 선언된 동일한 자료구조와도 호환성을 잃게된다. 다른 언어에선 '가상 함수 테이블 포인터' 라는 vptr이 없기때문이다.
그렇기때문에 가상 소멸자를 선언하는것은 그 클래스에 가상 함수가 하나라도 있을 경우에만 선언하고, 가상 함수가 없을때에는 가상 소멸자를쓰지말자!
하지만 모든 기본 클래스가 다형성을 갖도록 설계된것은 아니다.
(표준 string타입, STL컨테이너타입)
그리고 기본클래스로는 쓰일 수 있지만, 다형성은 갖지않도록 설계된것도 있다.
(Uncopyable, 표준 라이브러리의 input_iterator_tag)
이런 클래스들은 파생 클래스 객체의 조작이 허용되지 앟기때문에 가상 소멸자를 볼 수 없다.
+) 순수 가상 소멸자를 이용하면 추상클래스를 쉽게 만들 수 있다.
우리가 아는 추상클래스는 보통 순수가상함수가 들어가 있다.
하지만 추상클래스이면 좋겠지만 넣을 순수 가상 함수가 없다면 굳이굳이 만들어서 넣을필요는 없고,
순수 가상 소멸자만 있더라도 추상클래스가 될 수 있다.
class AWOV {
public:
virtual ~AWOV() =0; //순수 가상 소멸자 선언
};
AWOV:: ~AWOV() {} //순수 가상 소멸자 정의
'STUDY > Effective C++' 카테고리의 다른 글
항목 9 : 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자 (0) | 2022.08.17 |
---|---|
항목 8: 예외가 소멸자를 떠나지 못하도록 붙들어 놓자 (0) | 2022.08.17 |
항목 6: 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해버리자 (0) | 2022.06.23 |
항목 5: C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자 (0) | 2022.06.23 |
항목 4: 객체를 사용하기 전에 반드시 그 객체를 초기화하자 (0) | 2022.06.23 |