'프로그래밍'에 해당되는 글 19건

  1. 2013.07.23 VFT(Virtual Function Table)
  2. 2013.07.23 RTTI(Run-Time Type Information)
프로그래밍/c++2013. 7. 23. 14:39

RTTI(Run-Time Type Information)에 이어서 VFT(Virtual Function Table)에 대한 설명을 이어 가겠습니다.

RTTI 예제 소스상에서 특정위치에 브레이크 포인터를 걸고 객체의 값들을 살펴보았습니다.

 

위에서 보시는바와 같이 객체의 값들을 살펴보니 __vfptr이라는 이름이 존재합니다.

vfptr는 virtual function pointer 의 약자이며 가상 함수 포인터로 해석이 되겠네요.

가상함수의 경우 컴파일단에서 어느 함수가 호출 될지 모르기때문에 별도의 VFT(Virtual Function Table:가상함수테이블)라는 메모리상에 가상함수들이 자리잡게 됩니다.

위의 이미지를 참고하여 보시면 derivedPointet 객체와 basePointer 객체에 가상함수포인터가 같은 위치를 가르키고 있을것을 볼수있습니다.

각각의 인스턴스마다 각각의 가상함수테이블을 생성하게 된다면 메모리 낭비를 일으킬수있으므로 가상함수테이블은 객체의 생성과 무관하게 별도의 메모리상에 생성됩니다.(Stack이나 Heap이 아닌 별도의 영역이라고 합니다. 정확히 어딘지는 저도 잘...누가 아시면 좀 알려주세요;;)

객체가 생성될때 __vfptr(가상함수포인터)를 이용하여 VFT를 가르키게 되고 특정 가상함수를 호출했을때 해당하는 가상함수포인터가 가르키고있는 함수를 호출하게끔 유도해줍니다.(자식클래스에서 오버라이딩 된 함수가 있다면 자식클래스의 가상함수를 호출, 없다면 부모클래스의 가상함수를 호출)

RTTI의 경우 부모, 자식 클래스간 함수호출을 위해 만들어진 기능?이다보니 RTTI에 대한 정보가 c++표준위원회에서 규정으로 VFT에 들어가는걸로 알고있습니다.(RTTI가 추가되면서 이 기능에 관련된 메모리를 적재할곳을 찾다가 적당한곳이 VFT라고 판단한듯.)

뭐...굳이 부모클래스에서 virtual 함수를 쓸일이 없는데 RTTI를 꼭 쓰셔야 겠다는 분은 소멸자에 virtual 키워드를 붙이는 방법도 있는듯 합니다.



Posted by GaePein
프로그래밍/c++2013. 7. 23. 12:29

그냥 갑자기 급 생각나서 정리해봅니다.

(처음 게임회사 기술면접에서 나왔던 용어인데 뭔지 몰라서 당황했던....)

RTTI : Run-time type information

예제를 보면서 설명하겠습니다.(위키에서 퍼온것에 약간 수정)

#include <iostream>

class Base
{
public:
 Base() { }
 virtual ~Base() { }

 virtual void hello()
 {
  std::cout << "in Base";
 }
};

class Derived : public Base
{
public:
 void hello()
 {
  std::cout << "in Derived";
 }

 void Bye()
 {
  std::cout << "out Derived";
 }
};

 

int _tmain(int argc, _TCHAR* argv[])
{
 // 부모객체에 자식클래스 동적할당
 Base* basePointer = new Derived();


//To find whether basePointer is pointing to Derived type of object
 Derived* derivedPointer = dynamic_cast<Derived*>(basePointer);

 // 다이나믹 캐스트가 성공했다면
 if (derivedPointer != nullptr)
 {
  std::cout << "basePointer is pointing to a Derived class object"; //Identified
 }
 // 다이나믹 캐스트가 실패했다면(derivedPointer  객체에 널값이 들어감.)
 else
 {
  std::cout << "basePointer is NOT pointing to a Derived class object";
 }

 //Requires virtual destructor
 delete basePointer;
 basePointer = nullptr;

 return 0;


}

 

간단히 주석달아봤는데 설명이 부족하네요;;

 

RTTI의 주사용목적은 부모객체로 자식클래스의 함수를 호출하고자 할때 유용합니다.

다이나믹 캐스트를 통해 만약 basePointer객체에 Derived 객체가 있다면 하향형변환을 통해 Derived객체를 리턴하게되고

만약 Derived 객체가 없다면 NULL 값을 리턴하게 되므로 널값체크만 하면 됩니다.

더 풀어서 이야기하자면 다이나믹캐스트를 했을때 형변환하려는 객체 basePointer가 자식클래스로 Derived 클래스를 가지고 있다면

Derived를 리턴 그렇지 않다면 NULL값을 리턴하게 되는것입닌다.

위의 방법이 아닌 RTTI를 사용하지 않는 경우 부모클래스에 virtual 함수를 통해 자식클래스의 함수를 호출 하는 방법이 있긴합니다.

예)

class Base
{
public:
 Base() { }
 virtual ~Base() { }

 virtual void hello()
 {
  std::cout << "in Base";
 }

// 아래와 같이 Derived 함수에 있던 Bye() 함수를 부모클래스에 가상함수로 정의

virtual void Bye(){}
};

 

 

위와 같은 방법은 부모클래스에는 범용적으로 자식들이 사용할 함수를 정의한다는 암묵적인 룰을 깨는 행위므로 그다지 좋지 못한 소스입니다.

자식클래스에서 필요한 함수를 부모클래스에 마구잡이로 정의해 버리면 상속을 안쓰는것만 못한 현상이....

부랴부랴 급하게 정리한거라 이해가 잘 될지 모르겠네요...;;

RTTI를 무분별하게 사용할 경우(하나의 함수안에서 다른 자식클래스로 여러번 캐스팅이 이루어질경우) 현재 부모객체가 어떤 자식클래스로 캐스팅되어있는지 모르게 될 경우가 있습니다.

아.. 한가지더 !!

참고로 RTTI를 쓰기위해선 꼭 부모클래스에 최소한 virtual 함수가 하나 이상은 있어야합니다.

그이유는 추후 virtual 함수의 원리에서 설명하는걸로...!!

뭐든지 적절히 적당히 쓰는게 좋습니다 ㅋ



Posted by GaePein