게임 개발/C++

[C++] 오버라이딩 - 4. 가상 소멸자

유행성바코드 2025. 2. 27. 22:57

목차

  • 01. Intro
  • 02. 가상 소멸자
  • 03. 마무리
  • 04. 연관 내용

01. Intro

지난 포스팅에서 오버라이딩을 마무리 지으려고 했지만, 오버라이딩에서 중요한 요소인 가상 소멸자에 대해서 추가로 알아보고자 합니다.

 


02. 가상 소멸자

가상 소멸자는 소멸자에 virtual 키워드를 사용한 것입니다.

 

#include <iostream>

using namespace std;

class Sport
{
public:
	Sport() {}
	~Sport()
	{
		cout << "Sport End" << endl;
	}
};

class Soccer : public Sport
{
public:
	Soccer() {}
	~Soccer()
	{
		cout << "Soccer End" << endl;
	}
};

int main()
{
	Soccer* soccer = new Soccer();
	Sport* sport = soccer;

	delete sport;

	return 0;
}

 

위 코드를 실행한 결과, 부모 클래스의 Sport 소멸자만 실행되는 것을 확인할 수 있었습니다.

 

그래서, 자식 클래스에서 소멸자를 통해 어떠한 행동을 할 수 없습니다.

 

이러한 상황에서 발생하는 문제점은 아래 코드를 보면서 살펴보겠습니다.

#include <iostream>

using namespace std;

class Player
{

};

class Sport
{
public:
	Sport() {}
	~Sport()
	{
		cout << "Sport End" << endl;
	}
};

class Soccer : public Sport
{
public:
	Soccer() {}
	Soccer(Player* player)
	{
		_player = player;
	}
	~Soccer()
	{
		cout << "Soccer End" << endl;
		delete _player;
	}
	Player* _player;
};

int main()
{
	Soccer* soccer = new Soccer(new Player());
	Sport* sport = soccer;

	delete sport;

	return 0;
}

만약에, Sport의 자식 클래스인 Soccer 클래스에서 Player에 대한 포인터 변수를 멤버 변수를 가진다고 가정하겠습니다.

이때, Soccer 클래스의 소멸자에서 _player 주소값이 가리키는 객체를 메모리 해제하고자 합니다.

 

main 함수에서 Soccer 클래스에 대한 객체의 동적 할당을 하고 이 주소값을 Sport 포인터 변수에 담았습니다.

sport 포인터 변수는 해당 주소값으로 가면, Sport 클래스의 객체가 있다고 생각을 합니다.

(실제로는 Soccer 클래스에 대한 객체가 있지만, Sport* 여서 Sport 클래스의 객체가 있다고 생각합니다.)

따라서, delete soccer을 하면, Sport 클래스에 대한 소멸자만 호출을 합니다.

 

결과적으로 Soccer 클래스의 소멸자가 호출되지 않았습니다.

동적 할당된 soccer 객체를 해제했지만, Soccer 클래스의 _player 포인터가 가리키는 객체는 해제되지 않는 문제가 발생합니다.

그래서, 소멸자에 대한 가상화를 해야 합니다.

 

#include <iostream>

using namespace std;

class Player
{

};

class Sport
{
public:
	Sport() {}
	virtual ~Sport()
	{
		cout << "Sport End" << endl;
	}
};

class Soccer : public Sport
{
public:
	Soccer() {}
	Soccer(Player* player)
	{
		_player = player;
	}
	~Soccer()
	{
		cout << "Soccer End" << endl;
		delete _player;
	}
	Player* _player;
};

int main()
{
	Soccer* soccer = new Soccer(new Player());
	Sport* sport = soccer;

	delete sport;

	return 0;
}

 

 

 

부모 클래스의 소멸자에 virtual 키워드를 붙이면, 실행했을 때, 다음과 같은 결과가 나옵니다.

가상 소멸자를 함으로써 Sport 객체의 _player 포인터 변수에 대해서도 메모리 해제를 합니다.

따라서, 가상 소멸자로 선언하면, 자식 클래스의 소멸자도 호출하게 됩니다.

 

번외로 부모 클래스의 함수를 가상 함수로 선언하면, 자식 클래스에서 virtual 키워드를 붙이지 않아도 가상 함수로 작동합니다.

 


03. 마무리

C++ 언어에 대해서 자세히 공부할수록 새로운 것이 나오네요..

공부하다가 추가로 더 알아낸 정보가 있으면 글로 포스팅하겠습니다!

 


04. 연관 내용

  • [C++] 오버라이딩 - 1. 정적 & 동적
 

[C++] 오버라이딩 - 1. 정적 & 동적

목차01. Intro02. 오버라이딩정적 오버라이딩동적 오버라이딩03. 마무리04. 연관 내용01. Intro오늘은 클래스를 상속받았을 때, 사용할 수 있는 함수 오버라이딩에 대해 알아보겠습니다. 02. 오버라이

epidemic-barcode.tistory.com

  • [C++] 오버라이딩 - 2. 가상 함수 테이블 & 포인터   
 

[C++] 오버라이딩 - 2. 가상 함수 테이블 & 포인터

목차01. Intro02. 가상 함수가상 함수 테이블 포인터가상 함수 테이블 03. 마무리04. 연관 내용01. Intro지난 시간에 오버라이딩 종류인 [정적 오버라이딩]과 [동적 오버라이딩]에 대해서 알아봤습니다

epidemic-barcode.tistory.com

  • [C++] 오버라이딩 - 3. 순수 가상 함수 
 

[C++] 오버라이딩 - 3. 순수 가상 함수

목차01. Intro02. 가상 함수 호출 과정 복습03. 순수 가상 함수정의 및 형태특징추상 클래스03. 마무리04. 연관 내용01. Intro지난 시간에 동적 오버라이딩인 가상 함수를 적용했을 때, 어떤 과정으로 동

epidemic-barcode.tistory.com

 


 

읽어주셔서 감사합니다.

틀린 내용 지적은 언제나 환영입니다!