가상 함수 테이블

보물창고·2021년 8월 3일
0

vTable 의 위치는? ??? 최근 추가 240221

https://guru.tistory.com/125?category=1038889

  • 최근 추가
    : virtual 키워드가 추가되는 순간 메모리의 시작값은 vTable로 결정되는 듯함.
    -> IocpCore 프로젝트에서 IocpEvent를 OVERLAPPED 캐스팅시
    -> 쓰레기값???? 이 나오는 문제 발생함.

핵심!

  • 위의 그림에서 출력문에 주의하자.
    : 당연히 객체 c랑 d는 클래스 a를 상속했으니까, a의 data 가 객체 c와 d의 메모리의 가장 꼭대기에 위치, 즉 객체 c와 d의 메모리값이 겠지? 라는 생각을 했는데...
    어머나..... 뭐냐 이게...
    &c, &d 보다도 &c.data , &d.data 는 4씩 다음 메모리에 위치함.

virtual 선언시 가상함수 테이블이 객체의 맨위, 즉 첫번째 메모리에 위치함.
: 만약 상속 관계에서의 형변환 발생시, 불가할 수 있음.
--> 이거를 도대체 왜한다고 생각할 수 있는데, 해야하는 상황이 발생해서 작성한 것임.


vTable이란?

: vitual Function Table이라고 하고, 클래스의 가상 함수의 포인터들이 저장되는 포인터 배열이다.

  • vTable
    부모클래스에 virtual이 선언되어 있는 멤버 함수가 있으면, 부모 클래스의 가상 함수 포인터들이 저장된 vTable이 생성되고, 자식클래스의 가상함수 포인터들이 저장된 vTable이 생성된다.

  • 내부적으로는
    부모 클래스 내부에는 부모 클래스의 vTable을 가리키는 포인터를 가지고 있고,
    자식 클래스 내부에는 자식의 vTable을 가리키는 포인터를 가지고 있다.

  • 호출하는 과정
    실형식이 부모일 경우, 부모의 vTable을 가리키는 포인터가 부모의 vTable로 이동해 vTable에 있는 해당 함수를 호출하게 된다.

virtual 적용시 클래스의 크기는?

  • 현재 내컴퓨터는 64비트이다.
    64비트에서 포인터의 크기는 8바이트임.

    : cat의 크기는 animal 클래스의 dAnimal 의 사이즈도 포함한 값이다.

  • virtual 키워드 사용

  • 메모리 프로세스로 나타내면 이와 같다.

=> 가상함수 테이블의 크기가 8바이트인것이다.
virtual 함수마다 8바이트씩 증가하는 것이 아님!

  • animal : double dAnimal + Animal의 가상함수 테이블
  • cat : double dAnimal + cat의 가상함수 테이블 + double dCat

-> virtual 키워드 사용으로 가상함수테이블을 가리키는 포인터가 각 클래스 마다
추가된 것이다.
이 때 Animal을 위한 가상함수 테이블, cat을 위한 가상함수 테이블로 나뉘어진다.
Animal의 가상함수 테이블에는 Animal 클래스 내부의 speak함수의 포인터를 가지고 있다.
cat의 가상함수 테이블에는 cat 클래스 내부의 speak함수의 포인터를 가지고 있다.

최종 코드

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

class Base
{
private :
	int pri;
protected:
	int pro;

public : 
	int pu;
	void setPir(int n)
	{
		pri = n;
	}

	void setPro(int n)
	{
		pro = n;
	}
};


class Derived : private Base
{
public : 
	void test()
	{
		//pu = 50;
		//pri = 100;
		//setPro(10);
	}
};

class Derived2 : public Derived
{
public:
	void test()
	{
		//pu = 50;
		//pri = 100;
		//setPro(10);
	}
};

void recur(int n, int&cnt)
{
	if (n == 0)
	{
		cnt++;
		return;
	}

	if(n - 1 >= 0)
		recur(n - 1, cnt);
	if (n - 2 >= 0)
		recur(n - 2, cnt);


}


class Animal
{
public : 
	virtual void speak()
	{
		cout << "Animal" << endl;
	}

	virtual ~Animal() = default;
	double dAnimal;
};
class Cat : public Animal
{
public:
	void speak() override
	{
		cout << "cat" << endl;
	}

	~Cat() = default;
	double dCat;

};

int main(void)
{
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);	
	
	cout << sizeof(Animal) << endl;
	cout << sizeof(Cat) << endl;

	//Animal * polyAnimal = new Cat();
	//polyAnimal->speak();
	//delete polyAnimal;
	
	return 0;
}

profile
🔥🔥🔥

0개의 댓글