-
[Effective C++] 07. 다형성과 소멸자C++/Effective C++ 2025. 12. 11. 15:42
원제목 : Declare destructors virtual in polymorphic base classes (다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자)
다형성이란 하나의 기본 클래스가 여러 종류의 파생 클래스로 이어나갈 수 있는 형태를 한 것을 의미합니다.
현실적인 예시를 들어보면, "시계"가 "손목시계", "회중시계", "벽시계"등의 개념으로 파생되는 것이 있겠습니다.
이와 같이 다형성을 가지는 클래스가 있을 경우, 이 클래스의 소멸자는 가상화 할 것을 권고합니다.
이번 글에서는 소멸자를 가상화하는 경우에 대해 알아보도록 하겠습니다.
1. 가상화 하지 않으면?
더보기소멸자를 가상화 하지 않았을 경우에 어떤 일이 일어나는지 알아보겠습니다.
다음 클래스는 시계를 나타낸 클래스입니다.
class Watch { public: ~Watch() { cout << "~Watch\n"; } }; class WristWatch : public Watch { public: ~WristWatch() { cout << "~WristWatch\n"; } }; Watch* foo = new WristWatch(); delete foo;이 코드의 foo는 명백한 WristWatch 객체입니다.
하지만 foo가 소멸될 때 호출되는 소멸자는 Watch의 소멸자입니다.
예시를 간단하게 만들었지만, WristWatch의 소멸자에 특정한 기능이 있다고 할 경우, 이것이 실행되지 않습니다.
소멸자의 가상화는 이런 문제를 해결할 수 있습니다.
class Watch { public: virtual ~Watch() { cout << "~Watch\n"; } }; class WristWatch : public Watch { public: ~WristWatch() override { cout << "~WristWatch\n"; } }; Watch* foo = new WristWatch(); delete foo;위와 같이 Watch의 소멸자를 가상화 하면 Watch와 WristWatch의 소멸자가 모두 호출됩니다.
기본 클래스의 함수가 가상 함수일 경우, 파생 클래스의 오버라이드되는 함수는 virtual키워드를 붙이지 않아도 가상화됩니다.
이번 글과는 관련성이 크지 않지만, override는 C++11이후 추가된 오버라이드 되는 함수임을 명시하는 키워드입니다.
컴파일 타임에 해당 함수가 상위 클래스의 가상 함수로부터 오버라이드되는 것인지 확인하는 키워드로, 코드의 안정성을 높혀주는 역할을 수행합니다.
2. 항상 가상화를 해야할까?
더보기이전 문단에서 보았듯, 특정 객체의 소멸자가 일부 호출되지 않는 것은 큰 문제로 이어질 수 있습니다.
하지만 그렇다고 모든 클래스의 소멸자를 가상화 하는 것은 좋지 않을 수 있습니다.
다음 클래스는 2D공간의 점을 나타내는 클래스입니다.
class Point{ public: Point(int xCoord, int yCoord); private: int x, y; };Point객체는 int 두 개를 멤버로 가지고 있으므로 8byte의 공간을 차지한다고 볼 수 있습니다.
이 객체는 점을 나타내는 데이터 클래스로, 상속을 통해 확장되는 것은 불필요하다고 볼 수 있습니다.
하지만 이 객체에 가상 함수 (가상 소멸자를 포함한)를 추가하게 될 경우, 가상 함수 테이블이 클래스에 추가됩니다.
이를 사용하기 위해 Point객체에 가상 함수 포인터가 추가되고, 이는 8byte입니다.
다형성이 불필요한 클래스에 가상 소멸자를 추가하면 불필요한 메모리 낭비로 이어질 수 있습니다.
가상 소멸자는 우리가 설계하는 클래스 뿐만 아니라, 다른 클래스를 사용할 때에도 중요하게 생각해야 합니다.
예를 들어, C++의 STL 컨테이너 대부분은 다형성을 지원하지 않습니다.
따라서 string, vector등을 상위 클래스로 가지는 클래스를 만들 경우, 소멸자 호출에 주의해야 합니다.
이번 글이 도움이 되셨기를 바랍니다.
감사합니다.
'C++ > Effective C++' 카테고리의 다른 글
[Effective C++] 09. 객체 생성, 소멸 시 가상 함수가 호출되지 않게 하자 (0) 2025.12.15 [Effective C++] 08. 소멸자의 예외 안정성 (0) 2025.12.11 [Effective C++] 06. 특수 멤버 함수의 자동 생성에 관하여 (2) (0) 2025.12.02 [Effective C++] 05. 특수 멤버 함수의 자동 생성에 관하여 (0) 2025.12.01 [Effective C++] 04. 객체를 사용하기 전에 반드시 초기화하자 (0) 2025.11.27