Casting operators #

C++에서는 4가지의 cast 연산자가 추가 되었습다.
물론 C언어와의 호환성을 위해 C언어의 문법도 지원합니다.
그러나 명확하고 보다 안전함 때문에 C++의 cast를 추천합니다.


static_cast #

사전적 의미는 런타임시 타입에 대한 체크와 cast가 이루어지는것이 아니고
컴파일시에 체크와 cast되는 연산자

일반적으로 C언어의 형변환이 여기에 속합니다.
그리고 base 클래스에서 derived 클래스로의 down cast시에도 이용되는데
런타임시 타입을 체크하지 않고 cast가 되기 때문에 오버헤드는 없으나
잘못된 포인터로 인한 위험은 존재합니다.
class Base {};
class Derived : public Base {};

void f(Derived *p)
{
}

int main()
{
  Base *p = new Derived;
  f(static_cast<Derived *p>(p)); // down cast 

  int i = 39;
  unsigned long lvalue = static_cast<unsigned long>(i); // 일반적인 cast 
  unsinged long lvalue2 = (unsigned long)i;  // C언어 cast도 지원 
}


reinterpret_cast #

다른 타입간의 형변환에 사용됩니다.
일반적으로 일반타입과 포인터간 혹은 서로 다른 타입의 포인터간 cast에 사용됩니다.
int main()
{
  int n = 90;
  char *p = reinterpret_cast<char *>(&n);  // 서로다른 포인터 

  int nHandle = reinterpret_cast<int>(p);  // 포인터와 일반타입 
}


const_cast #

const, volatile 두개의 키워드로 선언된 변수의 속성을 제거하는 cast 입니다.
const_cast는 상수성및 휘발성의 성질을 제거할때만 사용되고 다른 현변환이나
클래스계층간 cast할수는 없습니다.
int main()
{
  const char sz[] = "TEST";
  char *p = const_cast<char *>(sz);
}


dynamic_cast #

static_cast와 상대적인 의미의 cast로서 클래스의 안전한 downcast에 이용됩니다.
dynamic_cast는 컴파일시 타입을 체크하는것이 아니고 런타임시 포인터의 타입이 아닌
실제로 가르키고있는 객체의 계층간 타입을 확인해 cast를 해주는 연산자이고
그로인해 약간의 오버헤드가 존재 합니다.

dynamic_cast의 기본개념은 virtual function table에 있는 들어있는 타입의 정보를
이용하기 때문에 virtual member function을 가지고 있는
Base클래스에서 상속받은 객체로의 cast만 가능합니다.

그리고 오버헤드로 인하여 몇몇 컴파일러들은 기본으로 이 기능을 끄고 사용할때 옵션으로서
기능을 켜고 사용할수 있게 제공됩니다
(대표적으로 VC++이 여기에 속합니다. VC++에서 dynamic_cast를 이용하려면
Project 세팅에서 옵션을 체크해줘야 됩니다.)

dynamic_cast의 행동은
포인터는 cast가 성공일 경우 해당 포인터를 cast가 실패일 경우 NULL로 세팅을 합니다.
참조의 경우는 cast가 실패하면 bad_cast Exception 이 발생합니다.
class NotVBase
{
public:
  ~NotVBase() {}
};
class NotVDerived : public NotVBase {};

class VBase
{
public:
  virtual ~VBase() {}
};
class VDerived : public VBase{};

int main()
{
  NotVBase *p = new NotVDerived;
  // ERROR   
  // 컴파일러에서 에러를 잡아 줄것 입니다. 
  // Base 클래스가 virtual member 가 존재하지 않습니다. 
  NotVDerived *pp = dynamic_cast<NotVDerived *>(p);   // 컴파일 에러   


  VBase *vp = new VDerived;
  VBase *nvp = new VBase;

  VDerived *vpp1 = dynamic_cast<VDerived *>(vp); // SUCCESS   

  // nvp가 가르키고 있는 포인터는 VDerived 타입이 아닙니다. 
  // 따라서 vpp 에는 NULL이 세팅됩니다.   
  VDerived *vpp2 = dynamic_cast<VDerived *>(nvp);
  if (!vpp2) {
    // 이부분이 실행됩니다.   
  }

  try {
    // 만약 참조로 cast하다 실패하면 bad_cast Exception이 발생합니다. 
    VDerived &vd = dynamic_cast<VDerived &>(*nvp);
  }
  catch (...) {}

}

dynamic_cast는 계층간의 downcast는 물론
다중상속으로 인한 Base 클래스끼리의 형변환도 해당이 됩니다.

class Base1
{
public:
  virtual ~Base1() {}
};

class Base2
{
public:
  virtual ~Base2() {}
};

class Derived : public Base1, public Base2
{

};

int main()
{
  Base1 *p1 = new Derived();

  // Base1 에서 Base2로의 형변환 
  // p1이 가르키고 있는 타입은 Derived 
  Base2 *p2 = dynamic_cast<Base2 *>(p1); // SUCCESS 

}

'Dev > C++' 카테고리의 다른 글

template  (0) 2008.05.01
functor - 함수객체  (0) 2008.05.01
export  (0) 2008.05.01
main function  (0) 2008.05.01
tr1::regex (boost::regex) 샘플코드  (0) 2007.10.21

+ Recent posts