C++ 가상 파괴자(virtual destructor)의 필요성

프로그래밍/C++ 2019.10.18 댓글 Plorence

일반적으로 파괴자에서 처리해야 할 작업이 없으면 파괴자 정의 자체를 안 하는 경우가 많습니다.

할당한 걸 해제해줘야 하는 경우 파괴자를 정의하고 처리해줘야 하는 게 정상입니다.

가상 파괴자는 다음과 같은 상황일때 필요합니다.

  • 기초, 파생 클래스에서 파괴자를 정의 한경우에 (필요로 할 때)

  • 업 캐스팅될 여지가 있는 경우에

 

가상 파괴자가 아닐 때

#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는 기초 파괴자, 파생 파괴자 둘 다 호출이 됩니다.

이때 기초 파괴자까지 호출되는 이유는, 파생 클래스가 소멸될 때 자연스레 기초 클래스의 객체도 사라지니 기초 파괴자가 호출이 됩니다.

 

결론은 메모리 누수 방지입니다.

댓글