C & C++

C++ <가상 함수의 동작 원리>

회민짱짱 2024. 1. 31. 03:29
V-Table & V-Pointer

 

가상 함수의 동작 원리를 이해하기 위해 꼭 필요한 개념인 V-Table와 V-Pointer에 대해 먼저 알아봅시다. 

 

V-Table 란?
- 하나 이상의 가상 함수를 가진 클래스에 대해서 컴파일러에서 만들며  바이너리 'rdata' 영역에 기록되는 테이블
- Key 와 Value 로 구성되어 있으며 Key 를 통해 Value 에 접근하는 방식으로  Key 에는 함수 식별자, Value 에는 함수의 주소 정보가 저장됨.

 

V-Pointer 란?
- V-Table 의 주소를 참조하는 포인터 변수로 가상 함수를 가진 클래스로 객체를 생성했을 때 그 생성된 각각의 객체가 V-Pointer 를 갖고있음.

 

V-Table 생성 원리 

 

AAA 라는 클래스가 존재하고 BBB 클래스가 이를 상속받는 상황을 생각해봅시다.

 

class AAA
{
private:
	int num1;
public:
	virtual void Func1() { cout << "Func1" << endl; }
	virtual void Func2() { cout << "Func2" << endl; }
};

 

먼저 AAA 클래스에는 가상함수로 Func1, Func2 가 존재합니다. 그렇다면 컴파일러에 의해 다음과 같이 V-Table 이 만들어집니다. 

 

AAA 클래스 V-Table

 

AAA 클래스를 상속받는 BBB 클래스를 정의합니다. 

 

class BBB : public AAA
{
private:
	int num2;
public:
	virtual void Func1() { cout << "BBB::Func1" << endl; }
	void Func3() { cout << "Func3" << endl; };
};

 

BBB 클래스 V-Table

 

여기서 중요하게 살펴보야할 점은 BBB 클래스의 V-Table 에는 AAA::Func1 함수의 정보가 없다는 것입니다. 

 

이처럼 함수가 오버라이딩 되는 경우에는 자식 클래스의 V-Table 에 오버라이딩 된 함수의 정보만 담게되므로 자식 클래스를 통해 오버라이딩 된 함수를 실행하면 무조건 가장 마지막에 오버라이딩을 한 자식 클래스의 멤버 함수가 호출됩니다.

 

V-Pointer

 

위 V-Table 생성 원리를 통해 V-Pointer 를 이해해 봅시다.

 

AAA 클래스로 객체를 만들게 되면 그 객체는 AAA 클래스의 V-Table 의 주소를 갖는 V-Pointer 변수를 갖습니다. 

 

BBB 클래스도 마찬가지로 객체를 만들게 되면 BBB 클래스의 V-Table 주소를 갖는 V-Pointer 변수를 갖습니다. 

 

따라서 클래스 내부에 멤버 함수는 객체 내부에 있지 않습니다. 

 

또한 한 클래스로 만든 여러 객체는 각각의 멤버 함수 V-Table 을 가지지 않고 하나의 V-Table 을 객체들이 공유하는 형태로 작동합니다.