가상 함수

khbin·2023년 11월 5일

가상함수를 이해하기 위해 오버라이딩을 먼저 설명한다.

오버라이딩 (Overriding)

class Monster
{
public:
	void DropItem()
	{
		cout << "Monster Drop" << endl;
	}
};

class Slime : public Monster
{
public:
	void DropItem()
	{
		cout << "Slime Drop" << endl;
	}
};

int main()
{
	Monster* parent = new Monster();
    Slime* child = new Slime();
    
	parent->DropItem();
    child->DropItem();
}

/*
(출력)
Monster Drop
Slime Drop
*/

이렇게 부모클래스(Monster)의 메소드를 자식클래스(Slime)에서 재정의 된 함수가 호출되고 있다.
이렇게 상속받은 함수를 자식클래스에서 재정의 하는 것을 오버라이딩(Overriding)이라고 한다.


조금 다르게 Monster 타입의 포인터 변수 monster에 Slime의 주소를 넣어보았다.

int main()
{
	Monster* parent = new Monster();
   	Monster* child = new Slime();
    
	parent->DropItem();
    child->DropItem();
}

/*
(출력)
Monster Drop
Monster Drop
*/

예상과는 다르게 둘 다 Monster Drop이 출력된다.
이렇게 포인터의 형에 따라 호출되는 메소드가 달라지는 것은 문제가 된다.
이유는 단순히 함수를 오버라이딩 하는 경우에 monster에 Slime의 주소를 넣어도 컴파일러는 monster의 변수가 Monster타입이기 때문에 Monster의 DropItem()을 바인딩하고 끝나게 된다.

이를 해결하기 위해 가상함수를 사용한다

class Monster
{
public:
	virtual void DropItem()
	{
		cout << "Monster Drop" << endl;
	}
	virtual void DropExp()
	{
		cout << "Monster Exp" << endl;
	}
};

class Slime : public Monster
{
public:
	void DropItem() override
	{
		cout << "Slime Drop" << endl;
	}
	void Split()
	{
		cout << "Slime Split" << endl;
	}
};
int main()
{
	Monster* parent = new Monster();
	Monster* child = new Slime();
	Slime* cchild = new Slime();

	parent->DropItem();
	child->DropItem();
	cchild->DropItem();
}
/*
(출력)
Monster Drop
Slime Drop
*/

'virtual' 키워드를 써서 원하는 결과를 얻게 되었다.
이처럼 가상함수를 사용하면 같은 타입으로 선언된 객체 포인터 변수라도 가리키고 있는 객체에 따라 오버라이딩 된 함수를 호출한다.
컴파일 시 가상함수가 정의된 클래스가 있다면 가상함수테이블이 만들어진다.


메인함수가 호출되기 이전에 다음의 구조로 가상함수 테이블이 메모리 공간에 할당된다. 참고로 가상함수 테이블은 객체의 생성과 상관없이 메모리 공간에 할당된다.
이는 가상함수 테이블이 멤버함수의 호출에 사용되는 일종의 데이터이기 때문이다.


Monster와 Slime의 객체가 생성되고 나면 위 그림과 같은 참조관계를 구성한다.
그림에서 보듯이 Monster 객체에는 Monster 클래스의 가상함수테이블의 주소 값이 저장되고 Slime 객체에는 Slime 클래스의 가상함수테이블의 주소 값이 저장된다.

가상함수를 하나 이상 멤버로 지니는 클래스의 객체에는 가상함수 테이블의 주소값이 저장된다.











[출처]
https://nomad-programmer.tistory.com/359
https://hwan-shell.tistory.com/223
https://cosyp.tistory.com/228

profile
틀린게 있다면 언제든지 알려주세요 감사합니다. 으라차차

0개의 댓글