본문 바로가기
Book & Lecture/Effective C++

Effective C++ 항목7 : 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자.

by studio ODOC 2023. 2. 5.
반응형

Effective C++ 항목7

 : 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자.

  • 객체에서 메모리 등 자원의 누수를 막기 위해서는 소멸자 호출
class TimeKeeper
{
  public:
    TimeKeeper();
    ~TimeKeeper();
    
    ...
};

class AtomicClock: public TimeKeeper { ... };
class WaterClock: public TimeKeeper { ... };
class WristClock: public TimeKeeper { ... };

...

// 팩토리 메서드 패턴
TimeKeeper* ptk = getTimeKeeper();

...

delete ptk;
  • 문제 발생!
    • 기본 클래스의 소멸자가 비가상 소멸자인 경우, 그의 파생 클래스가 삭제될 때 프로그램의 동작이 미정의 사항. (보통은 파생 클래스가 소멸되지 않음)
    • 해결책 : 기본 클래스의 소멸자를 가상 소멸자로 만듦
virtual ~TimeKeeper()
  • 가상함수를 포함한 클래스는 무조건 가상 함수 테이블 포인터라고 하는 자료구조를 갖게 됨
    • 포인터 크기는 아키텍처와 관계 (32비트 환경이라면 포인터 크기는 32비트, 64비트 환경이면 64비트)
  • 메모리 비효율을 막기 위해서 가상 함수가 하나라도 있는 클래스에 대해서만 가상 소멸자 선언할 것!
class SpecialString: public std::string { ... }; // STL 은 가상 소멸자가 없음

SpecialString *pss = new SpecialString("Doom");
std::string* ps;
. . .
ps = pss;
. . ..
// 정의되지 않은 동작 발생
// SpecialString 의 소멸자가 호출되지 않아서
// *ps 의 SpecialString 부분에 있는 자원 누출
delete ps;
  • 순수 가상 소멸자가 유용하게 쓰이는 다른 예
    • 1) 추상 클래스로 만들고 싶은 클래스인데, 어떤 함수를 가상 함수로 두어야할지 모르겠다면?
      • => 순수 가상 소멸자 선언!
반응형