본 문서는 가상 함수의 구체적인 작동 방법에 관하여 다룬다.
한 개 이상의 가상 함수를 포함하는 클래스에 대해서는 컴파일러가 다음 그림과 같은 형태의 가상 함수 테이블이라는 것을 만든다. 간단히 ‘V-Table(Virtual Table)‘이라고도 하는데, 이는 실제 호출되어야 할 함수의 위치 정보를 담고 있는 테이블이다.
클래스의 객체가 생성되면 객체는 클래스의 가상 함수를 참조할 수 있는 주소 값을 저장한다.
#include <iostream>
using namespace std;
class AAA
{
private :
int num;
public :
virtual void Func1() { cout<<"Func1"<<endl; }
virtual void Func2() { cout<<"Func2"<<endl; }
};
class BBB : public AAA
{
private :
int num2;
public :
virtual void Func1() { cout<<"BBB::Func1"<<endl; }
void Func3() { cout<<"Func3"<<endl; }
};
int main(void)
{
AAA *aptr = new AAA();
aptr->Func1();
AAA *bptr = new BBB();
bptr->Func1();
return (0);
}

가상 함수 테이블에는 key가 있고 value가 있다. 여기서 key는 호출하고자 하는 함수를 구분지어주는 구분자의 역할을 한다. 그리고 value는 구분자에 해당하는 함수의 주소정보를 알려주는 역할을 한다. 그래서 AAA 객체의 Func1 함수를 호출해야 하는 경우, 위의 테이블에 첫 번째 행의 정보를 참조하여 0x1024번지에 등록되어 있는 Func1 함수를 호출하게 되는 것이다.
가상 함수의 중요한 특징은 자식 클래스의 가상 함수 테이블에는 부모 함수의 오버라이딩 되기 전 가상 함수의 정보가 포함되지 않는다는 것이다. 그래서 오버라이딩 된 가상 함수를 호출하면, 무조건 가장 마지막에 오버라이딩을 한 자식 클래스의 멤버 함수가 호출된다.
참고자료