소멸자에 virtual
옵션이 왜 필요할까? 직관적으로 설명하면, 컴파일이 안된다…!
아래 코드는 AAnimal
이라는 추상클래스와 추상클래스를 상속받는 Cat
과 Dog
클래스가 있다.
main
에서 추상클래스 타입으로 Dog
객체를 new
로 생성하고, 가리키는 포인터를 ani
생성했다. 그 후 delete
로 해제를 시도했다.
Animal 은 추상 클래스이지만, 가상 소멸자가 아니라는 에러가 출력되면서 컴파일에 실패한다.
AAnimal
클래스의 소멸자에 virtual 을 입력하면 자연스럽게 해결된다. (Cat 과 Dog 의 소멸자에 virtual 은 생략 가능하다.)
그렇다면 왜 컴파일이 안될까? 이는 다음 블로그를 참고하면 쉽게 이해할 수 있다.
상속을 받은 클래스의 생성과 소멸 과정을 보면,
생성자는 부모 클래스의 생성자 → 자식 클래스
순서로 불려지고,
소멸자는 자식 클래스의 소멸자 → 부모 클래스
로 불려진다.
기억해야할 특징이 있다. 다형성을 이용하기 위해 부모 클래스의 포인터로 자식 클래스를 호출할 때, 가상 함수로 정의되어 있지 않은 자식의 오버라이딩된 함수를 호출하면 부모의 멤버 함수가 호출된다.
마찬가지로 소멸자도 자식 클래스에서 오버라이딩된 함수라고 볼 수 있기 때문에 만약 부모 포인터로 객체를 삭제하면 부모 클래스의 소멸자가 호출된다.
그렇기 때문에 소멸자를 가상 함수로 선언하지 않으면, 자식 클래스의 소멸자는 호출되지 않는다. 가상 함수 키워드 virtual
이 사용되었다면 이것은 자식 클래스에서 재정의될 수 있음을 명시하고, 포인터의 종류에 상관없이 항상 자식 클래스의 메서드가 호출된다.
즉, 자식 클래스의 소멸자가 호출되고 나서 부모 클래스의 소멸자가 호출된다. 따라서 상속 관계가 있고 해제해야 하는 상황이라면 반드시 소멸자를 가상 함수로 선언해야 한다.
코드 예시는 아래 블로그에서 잘 되어있다!