가상 소멸자는 어떤 경우에 쓰는 건가요?

조회수 12463회

제가 생성자나 다른 함수에 virtual붙는 건 이해하겠는데 소멸자에 virtual은 왜 쓰는 건지는 잘 모르겠어요.

객체가 소멸할 땐 상속받은 클래스의 소멸자도 자동으로 불러주잖아요? 근데 virtual을 써주는 게 무슨 의미가 있죠?

1 답변

  • 좋아요

    3

    싫어요
    채택 취소하기

    가상 소멸자는 derived class 인스턴스를 가리키는 base class pointerdelete할 때 유용하게 쓰입니다.

    class Base{
    public:
        ~Base() {
            cout << "Base destructor!" << endl;
        }
    };
    
    class Derived : public Base{
    public:
        char* largeBuffer;
        Derived() {
            largeBuffer = new char[3000];
        }
    
        ~Derived() {
            cout << "Derived destructor!" << endl;
            delete[] largeBuffer;
        }
    };
    

    위 코드는 base의 소멸자를 virtual로 설정하지 않았습니다. 이 상황에서 다음의 코드1,2는 같은 일을 할까요?

    소스코드

    int main(){
        //코드1
        cout << "---Derived* der1 = new Derived()---" << endl;
        Derived* der1 = new Derived();
        delete der1;
    
        //코드2
        cout << "\n\n---Base* der2 = new Derived()---" << endl;
        Base* der2 = new Derived();
        delete der2;
    
    }
    

    결과)

    ---Derived* der1 = new Derived()---
    Derived destructor!
    Base destructor!
    
    
    ---Base* der2 = new Derived()---
    Base destructor!
    

    코드1의 경우에는 말씀하신 것처럼 Drived class의 소멸자가 알아서 Base Class의 소멸자를 불러 줍니다. 그래서 buffer가 잘 delete 되었지요.

    그런데 코드2의 경우는 Derived destructor가 불리지 않았습니다. buffer가 delete 되지 않고 어딘가에 남아 있겠지요. Base 포인터가 Derived 클래스의 인스턴스를 가리키고 있지만 Derived의 멤버에 접근할 수 없어 이런 결과가 나타난 것입니다

    가상 소멸자는 이런 상황에서 메모리가 누수되는걸 막기 위해 씁니다.

    class Base{
    public:
        virtual ~Base() {
            cout << "Base destructor!" << endl;
        }
    };
    

    과 같이 Base 소멸자를 virtual로 설정하면 이젠 코드2의 경우에도 Derived class의 소멸자가 호출되어 메모리가 정상적으로 해제됩니다.

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)