[C++] 가상 함수(Virtual Function)

가상 함수는 객체 지향 프로그래밍에서, 상속 받는 클래스 내에서 오버라이딩 될 수 있는 함수입니다.
virtual 키워드를 붙여 사용가능합니다.
virtual을 붙이면 파생 클래스에서 재정의할 것으로 보이는 멤버 함수를 의미합니다.

사용 방법은 아래와 같습니다.

virtual (부모클래스의 멤버함수 원형)

우선 아래 코드를 보며 virtual이 없는 상태에서 동작을 설명하겠습니다.

#include <iostream>

using namespace std;

class CParent
{
public:
	CParent() {}
	~CParent() {}

	void Print() { cout << "Parent Print Function" << endl; }
};

class CChild : public CParent
{
public:
	CChild() {}
	~CChild() {}

	void Print() { cout << "Child Print Function" << endl; }
};


int main()
{
	CChild Child;
	CParent* pParent = &Child;

	pParent->Print();

	return 0;
}

CParent를 상속받은 CChild 클래스가 있고, main 함수에서 CChild를 생성 하고 CParent *형으로 주소를 받습니다.
pParent에서 Print 함수를 호출하면 아래와 같이 CParent::Print 함수가 호출됩니다.

만약 아래 코드와 같이 CParent에 virtual 함수를 추가해서 호출하면 어떻게 될까요?

class CParent
{
public:
	// 생략
	virtual void Print_1() { cout << "Parent Print 1 Function" << endl; }
};

class CChild : public CParent
{
public:
	// 생략
	virtual void Print_1() { cout << "Child Print 1 Function" << endl; }
};

int main()
{
	// 생략
	pParent->Print_1();
}

CCParent 클래스의 멤버함수에 virtual을 붙이면 CChild 클래스 멤버함수도 자동으로 가상 함수가 됩니다.
CChild 클래스 가상 함수에 virtual을 붙여 명시적으로 표현하는 방법도 있습니다.
중요한 것은 부모 클래스 소멸자 또한 가상 함수로 선언해야한다는 것입니다.

아래와 같이 구현하고 실행해 봅니다.

class CParent
{
public:
	// 생략
	~CParent() { cout << "Parent ~CParent Function" << endl; }
};

class CChild : public CParent
{
public:
	// 생략
	~CChild() { cout << "Child ~CChild Function" << endl; }
};

int main()
{
	CParent* pParent = new CChild;
	delete pParent;
	return 0;
}

CChild로 생성했지만 CParent의 소멸자가 수행되게 됩니다.
~CParent앞에 virtual 키워드를 붙임으로써 아래와 같이 CChild 뿐만 아니라 CParent의 소멸자도 호출됩니다.

#include <iostream>

using namespace std;

class CParent
{
public:
	CParent() {}
	virtual ~CParent() { cout << "Parent ~CParent Function" << endl; }

	void Print() { cout << "Parent Print Function" << endl; }
	virtual void Print_1() { cout << "Parent Print 1 Function" << endl; }
};

class CChild : public CParent
{
public:
	CChild() {}
	virtual ~CChild() { cout << "Child ~CChild Function" << endl; }

	void Print() { cout << "Child Print Function" << endl; }
	virtual void Print_1() { cout << "Child Print 1 Function" << endl; }
};


int main()
{
	CParent* pParent = new CChild;

	pParent->Print();
	pParent->Print_1();

	delete pParent;

	return 0;
}

전체 코드는 위와 같습니다.