일반적으로 파괴자에서 처리해야 할 작업이 없으면 파괴자 정의 자체를 안 하는 경우가 많습니다.
할당한 걸 해제해줘야 하는 경우 파괴자를 정의하고 처리해줘야 하는 게 정상입니다.
가상 파괴자는 다음과 같은 상황일때 필요합니다.
-
기초, 파생 클래스에서 파괴자를 정의 한경우에 (필요로 할 때)
-
업 캐스팅될 여지가 있는 경우에
가상 파괴자가 아닐 때
#include <iostream>
using namespace std;
class Person {
public:
~Person() {
cout << "기초 파괴자 \n";
}
Person() {
}
};
class Man : public Person {
public:
~Man() {
cout << "파생 파괴자 \n";
}
};
int main(void) {
Person * per = new Man();
Person * per1 = new Person();
delete per;
delete per1;
int a = 0;
}
기초 파괴자
기초 파괴자
호출된 파괴자들이 가상이 아니라면 포인터형에 해당하는 파괴자만 호출됩니다.
Man이라는 파생 클래스를 가리켜도 파생 클래스의 파괴자는 호출되지 않습니다.
파생 클래스에서 파괴자가 해야 할 작업이 있을 때는 치명적인 문제가 발생하게 됩니다.
가상 파괴자 일 때
#include <iostream>
using namespace std;
class Person {
public:
virtual ~Person() {
cout << "기초 파괴자 \n";
}
Person() {
}
};
class Man : public Person {
public:
~Man() {
cout << "파생 파괴자 \n";
}
};
int main(void) {
Person * per = new Man();
Person * per1 = new Person();
delete per;
delete per1;
int a = 0;
}
파생 파괴자
기초 파괴자
기초 파괴자
가상 파괴자면 객체형에 해당하는 파괴자가 호출됩니다.
포인터형이 어떤 거 든 간에 가리키고 있는 객체형의 파괴자가 호출됩니다.
이렇게 되면 파생 클래스의 파괴자, 기초 클래스의 파괴자가 호출되며 파생 클래스의 파괴자가 먼저 호출됩니다.
그래서 per는 기초 파괴자만 호출되고
per1는 기초 파괴자, 파생 파괴자 둘 다 호출이 됩니다.
이때 기초 파괴자까지 호출되는 이유는, 파생 클래스가 소멸될 때 자연스레 기초 클래스의 객체도 사라지니 기초 파괴자가 호출이 됩니다.
결론은 메모리 누수 방지입니다.
댓글