인프런 커뮤니티 질문&답변

yoodud님의 프로필 이미지

작성한 질문수

홍정모의 따라하며 배우는 C++

12.6 가상 (함수) 표

Virtual Table에 관해 질문 있습니다.

작성

·

17

1

 

강의 중 궁금한 내용이 있어 질문 드립니다.

class Base에 대한 Base VTable에 함수 fun1(), fun2()

class Der에 대한 Der VTable에 fun1(), fun2() 이렇게 있다고

말씀해 주신 것 같은데요.

실제로 디버깅해 보니 위에 설명하신 것처럼 Base VTable은 보이지 않고 자식 Der VTable에 함수 모든 함수가 들어가 있는 것 처럼 보이더라구요.

실제로 virtual 함수가 아닌 일반 함수도 추가해 보았는데,

일반 함수까지 vftable 사이즈에 잡혀 있었습니다.

 

질문을 정리 하자면

  1. 상속 받은 클래스의 VTable 하나로 가상함수 관리 하고 있는게 맞나요?

  2. vftable에 일반 함수들도 있지만, 가상 함수만 목록에 보여 주는건가요?

  3. 그리고 _vfptr에 있는 함수 주소는 실제 그 함수의 주소가 아니라 _vfptr배열 인덱스(순서)의 주소 인건가요?
    (테스트해 보니 함수 주소와 _vfptr배열에 있는 주소가 달라서 여쭤 봅니다.)

 

질문1.png.webp

테스트 코드

#include <iostream>

using namespace std;

class Parents
{
public:
	virtual void Func1()
	{
		cout << "void A::Func1" << endl;
	}

	virtual void Something()
	{
		cout << "void A::Something" << endl;

	}
	void Func2()
	{
		cout << "void A::Func2" << endl;
	}

};

class Child : public Parents
{
public:
	void Func1() override
	{
		cout << "void B::Func1" << endl;
	}

	virtual void Func3()
	{
		cout << "void B::Func3" << endl;
	}
};


int main() 
{
	Parents* parents = new Child();
	Parents* parents2 = new Parents();
	Child* child = new Child();

	parents2->Func1();
	parents->Func1();
	parents->Func2();
	child->Func3();
	child->Something();


	return 0;
}

 

답변 1

2

안녕하세요? 질문&답변 도우미 Soobak 입니다.


항상 꼼꼼히, 적극적으로 학습하시는 모습이 인상깊네요.
질문주신 내용들에 대해서 정리하여 답변 드립니다.

각 클래스는 자신만의 가상함수표를 가지게 됩니다.
이 때, 질문자님의 디버거에서 '자식 객체의 가상함수표' 만 보이는 이유는 현재 디버깅 중인 객체가 자식 객체이기 때문입니다. (혹시, 혼동이 되신다면 해당 강의 2:15 부분의 강의 화면과 3:45 부분의 강의 화면에서 VTable 을 비교해보시면 이해에 도움이 되실 것 같습니다.)

 

또한, 가상함수표에 일반 함수가 있는 것은 아닙니다. 가상 함수만 가상함수표에 포함됩니다.
이전 강의에서 학습하신 내용처럼, 일반 함수는 컴파일 시점에 정적으로 바인딩됩니다.
편의를 위해 디버깅 도구에서 가상함수표 정보와 함께 보여질 수는 있지만, 실제 가상함수표의 일부가 아닙니다.


vfptr 은 가상함수표의 시작을 가리키는 포인터이고, 가상함수표의 각 항목은 실제 함수의 메모리 주소를 가리킵니다. 하지만, 이 과정에 대한 컴파일러 최적화로 인해서 디버깅 도구를 통해 살펴보시는 함수의 주소가 달라질 수 있습니다.
이에 대해서는 virtual thunk 라는 키워드로 검색을 해보시면 도움이 되실 것 같습니다.
하지만, 지금 단계에서는 충분히 꼼꼼히 공부를 잘 하고 계시니, 핵심 내용만 이해를 하셨다면 이어서 학습을 하시는 것을 추천드립니다.

 

간단하게 핵심 내용을 정리 드려보면,
각 클래스는 자신만의 가상함수표를 가지며, 이 표에는 일반 함수가 아닌 가상 함수만이 포함됩니다.
이 때, 가상함수표의 각 항목은 실제 함수의 주소를 가리킵니다.
가상함수 호출시에는 객체의 vptr 을 이용하여 해당 클래스의 가상함수표에 접근하며,
접근한 표에서 해당 함수의 실제 주소를 찾아 함수를 실행하게 됩니다.

꾸준히 질문을 주셔서 감사하고 반갑습니다. 응원 많이 하고 있습니다.

yoodud님의 프로필 이미지
yoodud
질문자

말씀해 주신 디버깅 타이밍에 virtual table을 확인해 보니 각자 가상 함수 테이블을 가지고 있더라구요. ㅎㅎ
좀 더 꼼꼼하게 강의를 따라 테스트해 봐야겠네요.

그리고 virtual thunk는 처음 들어보는데 알려주신 내용 한번 알아보고 넘어가도록 하겠습니다.

virtual Table에 대한 궁금증이 해결 되어서 너무 좋네요.

언제나 꼼꼼하게 질문에 대한 답변 남겨 주시고 응원해 주셔서 감사합니다~
질문에 대한 답이 달리는 걸 기다리게 됩니다. ㅎㅎ
좋은 하루 보내세요~ 😄

 

yoodud님의 프로필 이미지

작성한 질문수

질문하기