WinAPI

Virtual Destructor(가상 소멸자)

Nin 2021. 1. 18. 23:42
#include <iostream>
class A
{
public:
    A()
    {
        std::cout << "A 생성자\n";
    }

    ~A()
    {
        std::cout << "A 소멸자\n";
    }
};

class B : public A
{
public:
    B()
    {
        std::cout << "B 생성자\n";
    }
    ~B()
    {
        std::cout << "B 소멸자\n";
    }
};

int main()
{
    B NewB = B();
}

위의 코드를 실행하면

A 생성자

B 생성자

B 소멸자

A 소멸자

위의 순서로 출력된다.여기서 알 수 있듯이 부모의 생성자가 먼저 호출되고

자식의 생성자 호출된후 자식의 소멸자, 부모의 소멸자 순으로 실행된다.

class B : public A
{
public:
   B() : A()
  {
     std::cout << "A 생성자\n";
  }
};

B의 생성자에는 위의 코드에서 보듯이 멤버이니셜라이즈로 A() 이 코드가 생략되있다.

그렇기때문에 안보이지만 언제나 호출된다.


#include <iostream>
class A
{
public:
    A()
    {
        std::cout << "A 생성자\n";
    }

    ~A()
    {
        std::cout << "A 소멸자\n";
    }
};

class B : public A
{
public:
    int* m_Value;
    
public:
    B()
    {
        m_Value = new int();
        std::cout << "B 생성자\n";
    }
    ~B()
    {
        delete m_Value;
        std::cout << "B 소멸자\n";
    }
};

int main()
{
    A* NewB = new B();
    delete NewB;
}

코드를 이렇게 수정하고 업캐스팅을 이용해서 자식형이 부모형이 되는 코드이다.

위이 코드를 실행하면 

A 생성자

B 생성자

A 소멸자

이렇게 출력된다.즉, B 소멸자가 호출되지 않은것이다.

부모의 자료형에서 자식의 멤버함수를 호출하지 못하는것과 같은것이다.

방법으로는 virtual 키워드로 가상함수로 만들고 자식에서 구현하면

그에 맞는 정의로 코드가 실행될것이다.소멸자도 이와 같은 이치다.

부모의 소멸자에 virtual 키워드를 붙여주지 않으면

동적 바인딩이 되었고 부모형으로 관리하고 있을때 소멸자가 호출되지 않는다.

일반적인 가상함수와 가상 소멸자의 다른점은 일반적인 가상함수는

함수의 이름이 부모와 같아야 하지만 소멸자만큼은 예외이다.

사실 소멸자는 컴파일러가 해석할때 ~클래스이름 으로 구별하는게 아니고

~붙어있으면 소멸자로 보기 때문이다.이는 소멸자에만 해당한다.


#include <iostream>
class A
{
public:
    A()
    {
        std::cout << "A 생성자\n";
    }

    virtual ~A()
    {
        std::cout << "A 소멸자\n";
    }
};

class B : public A
{
public:
    int* m_Value;
    
public:
    B()
    {
        m_Value = new int();
        std::cout << "B 생성자\n";
    }
    ~B() override
    {
        delete m_Value;
        std::cout << "B 소멸자\n";
    }
};

int main()
{
    A* NewB = new B();
    delete NewB;
}

이렇게 사용해야 한다.