본문 바로가기
개발/C, C++

C++ - 가상 소멸자 (Virtual Destructor)

by 피로물든딸기 2021. 8. 23.
반응형

C, C++ 전체 링크

 

virtual 예시에서 사용한 코드에서 소멸자를 추가한 후, foodList의 메모리를 해제해보자.

각 class에 생성자를 추가하고 foodList[0]은 new FOOD로 수정하였다.

#include <stdio.h>
#include <iostream>

using namespace std;

class FOOD
{
private:
	int price = 0;
public:
	FOOD() { printf("FOOD created\n"); }
	~FOOD() { printf("FOOD deleted\n"); }

	virtual void printName() { cout << "FOOD Class" << endl; }
	virtual void printPrice() { cout << this->price << endl; }
	void printLine() { cout << "=================" << endl; }	
};

class SNACK : public FOOD
{
private:
	int price = 1000;
public:
	SNACK() { printf("SNACK created\n"); }
	~SNACK() { printf("SNACK deleted\n"); }

	void printName() { cout << "SNACK Class" << endl; }
	void printPrice() { cout << this->price << endl; }
};

class MILK : public FOOD
{
private:
	int price = 500;
public:
	MILK() { printf("MILK created\n"); }
	~MILK() { printf("MILK deleted\n"); }

	void printName() { cout << "MILK Class" << endl; }
	void printPrice() { cout << this->price << endl; }
};

int main(void)
{
	FOOD* foodList[3];

	foodList[0] = new FOOD();
	foodList[1] = new MILK();
	foodList[2] = new SNACK();

	printf("\n---- TEST START ----\n\n");

	for (int i = 0; i < 3; i++)
	{
		foodList[i]->printName();
		foodList[i]->printPrice();
		foodList[i]->printLine();
		putchar('\n');
	}

	for (int i = 0; i < 3; i++) delete foodList[i];

	return 0;
}


FOOD를 상속받은 MILK와 SNACK은 FOOD 생성자가 호출된 후, MILK / SNACK 생성자가 호출되지만,

소멸자에서는 FOOD의 소멸자만 호출되고 있다.

 

Parent p = new Child() → 형변환이 이루어진 포인터 변수이기 때문에 원래 형태(부모)의 함수/소멸자 호출된다. 

 

이 코드에서는 큰 문제가 없지만, 만약 SNACK이나 MILK가 소멸되면서 메모리를 해제해야할 경우,

SNACK과 MILK의 소멸자가 호출되지 않기 때문에 메모리 누수 문제가 발생할 수 있다.

 

문제를 해결하는 방법은 소멸자도 virtual로 선언하는 것이다.

class FOOD
{
private:
	int price = 0;
public:
	FOOD() { printf("FOOD created\n"); }
	virtual ~FOOD() { printf("FOOD deleted\n"); } /* 가상 소멸자 */

	virtual void printName() { cout << "FOOD Class" << endl; }
	virtual void printPrice() { cout << this->price << endl; }
	void printLine() { cout << "=================" << endl; }
};

 

부모의 소멸자에 virtual로 선언하면, 자식의 소멸자가 먼저 호출된 후, 부모의 소멸자가 호출되어

정상적으로 메모리를 해제할 수 있게 된다.

반응형

'개발 > C, C++' 카테고리의 다른 글

C++ - 형변환 연산자 (casting operators)  (0) 2021.08.26
C++ - virtual / override 키워드  (0) 2021.08.25
C++ - explicit 키워드  (0) 2021.08.22
C++ - virtual, type casting  (0) 2021.08.15
C++ - virtual 키워드  (0) 2021.08.14

댓글