C++/C++
가상 소멸자
Elan
2021. 10. 11. 20:51
가상 소멸자란?
클래스의 가상 함수를 정의할 때 주의할 점은 소멸자도 가상함수로 만들어야 한다는 것이다.
부모 클래스 포인터가 동적으로 생성한 자식 클래스의 객체를 가리키도록 할 경우,
사용이 끝나면 동적으로 생성된 객체를 해제해야한다.
그럴 경우 부모 클래스로 생성된 포인터를 delete 해야한다.
이 때 포인터가 부모 클래스이므로 부모 클래스의 소멸자만 호출된다면 어떻게 될까?
부모 클래스의 소멸자만 호출된다.
즉, 자식 클래스는 소멸자를 호출받지 못했기 땜누에 내부에 있는 메모리 해제가 필요한 변수들을 해제하지 못하게된다.
이를 줄이기 위해 부모 클래스의 포인터가 소멸하더라도 자식 클래스의 소멸자가 함께 호출 될 수 있도록 소멸자 앞에 virtual 키워드를 붙여 가상 소멸자로 만들면 된다.
struct Point {
Point(int _x, int _y) { x = -_x; y = _y; }
int x, y;
};
class Shape {
protected:
Point startPoint, endPoint;
public:
Shape(Point _p1, Point _p2) :startPoint(_p1), endPoint(_p2) {}
virtual ~Shape() { std::cout << "Shapre 소멸자 호출\n"; }
void SetStartPoint(int _x, int _y) { startPoint = Point(_x, _y); }
void SetEndPoint(int _x, int _y) { endPoint = Point(_x, _y); }
virtual void Draw() const
{
std::cout << "Draw " << typeid(this).name() << std::endl;
}
};
class Rectangle : public Shape {
public:
Rectangle() :Shape(Point(0, 0), Point(0, 0)) { }
Rectangle(Point _start, Point _end) :Shape(_start, _end) {}
int GetWidth() const {
return endPoint.x - startPoint.x;
}
int GetHeigh() const {
return endPoint.y - startPoint.y;
}
void Draw() const
{
std::cout << "Draw " << typeid(this).name() << std::endl;
}
~Rectangle() {
std::cout << "Rectangle 소멸자 호출\n";
}
};
class Eclipse : public Shape {
public:
Eclipse() :Shape(Point(0, 0), Point(0, 0)) { }
Eclipse(Point _start, Point _end) :Shape(_start, _end) {}
bool IsCircle() const { return true; }
void Draw() const
{
std::cout << "Draw " << typeid(this).name() << std::endl;
}
~Eclipse() {
std::cout << "Eclipse 소멸자 호출\n";
}
};
int main()
{
Shape* pRect = new Rectangle;
pRect->SetStartPoint(0, 0);
pRect->SetEndPoint(100, 100);
pRect->Draw();
delete pRect;
ENDL; ENDL;
Shape* pEclipse = new Eclipse;
pEclipse->SetStartPoint(0, 0);
pEclipse->SetEndPoint(100, 100);
pEclipse->Draw();
delete pEclipse;
}