Skip to content
mooneegee edited this page Nov 19, 2013 · 2 revisions

Table of Contents

Cast

  • 형을 변환하는 것
  • static_cast, reinterpret_cast, const_cast, dynamic_cast가 있다.

C에서의 casting

  • 서로 유사성이 없는 자료형 간에도 형변환이 가능하다.
  • 편리하게 사용할 수 있다는 장점은 있지만 엄격하지 못한 형변환으로 실수가 발생할 수도 있다.

C++에서의 casting

  • C에서의 형변환을 동일하게 지원한다.
  • 클래스에 대한 형변환도 지원한다.
  • C에서의 형변환과 동일하게 사용했을 때, 문제가 발생할 수 있다.
class Child{};
class Person{};

int _tmain(int argc, _TCHAR * argv[])
{
	Child *pC = new Child();
	Person *pP;

	pP = (Person *)pC;  // 컴파일은 가능하나, Child 클래스와 Person 클래스 간에는 아무런 관계가 없으므로 문제

	delete pC;

	return 0;
}
  • 위의 코드처럼 C 스타일로 casting 하였을 때는 잠재적으로 문제를 발생시킬 수 있기 때문에 4가지 타입의 명시적 캐스팅 연산자를 추가로 지원한다.
  • C 스타일의 casting은 사용하지 않는 것이 좋다.

static_cast

  • 캐스팅이 묵시적으로 일어나는 경우 이를 명시적으로 형변환하겠다라고 분명히 해주는 용도로 사용된다.
  • 논리적으로 변환 가능한 타입으로만 변환할 수 있다.
  • 클래스의 경우 상속관계를 따져보고 변환하며 상호호환 관계가 아니면 컴파일 에러를 발생시켜 개발자가 에러를 발견하기 쉽게 해준다.
  • 대부분 이 캐스트를 사용한다.
  • int나 float를 서로 변환할 때 사용한다.
  • const가 붙어 있는 형에서 const가 없는 형으로 변환할 수는 없다.
int main()
{
	char *str = "korea";
	int *pi;
	double d = 123.456;
	int i;

	i = static_cast<int>(d);                  // 가능
	pi = static_cast<int *>(str);            // 에러
	pi = (int *)str;                          // 가능
}
class Parent { };
class Child : public Parent { };

int main()
{
	Parent P, *pP;
	Child C, *pC;
	int i = 1;

	pP = static_cast<Parent *>(&C);     // 가능
	pC = static_cast<Child *>(&P);      // 가능하지만 위험
	pP = static_cast<Parent *>(&i);     // 에러
	pC = static_cast<Child *>(&i);      // 에러
}
pP = static_cast<Parent *>(&C);
  • 위의 코드는 업 캐스팅이므로 가능하다.
    • 업 캐스팅 - 부모 클래스로 자식 클래스를 캐스팅하는 경우
pC = static_cast<Child *>(&P);
    • 위의 코드는 다운 캐스팅이므로 위험하다.
    • 다운 캐스팅 - 자식 클래스로 부모 클래스를 캐스팅하는 경우(부모 객체가 자식 클래스의 모든 멤버를 가지고 있다고 확신할 수 있는가? 없다.)

reinterpret_cast

  • 임의의 포인터 타입까리 변환을 허용하는 캐스팅 연산자이다.
  • 강력한 만큼 위험도 크다.
  • 강제 변환이므로 안전하지 않고 전적으로 개발자가 책임지고 관리해야 한다.(사용하지 않는 것이 답인듯 하다.)
int *pi;
char *pc;

pi = reinterpret_cast<int *>(12345678);
pc = reinterpret_cast<char *>(pi);
  • 이 연산자는 포인터 타입 간의 변환이나 포인터와 수치형 데이터의 변환에만 사용할 수 있다.
  • 기본 타입들끼리의 변환에는 사용할 수 없다.(정수형->실수형 불가능)

const_cast

  • const 또는 volatile의 속성을 변경할 때 사용한다.
  • 상수 지시 포인터를 비상수 지시 포인터로 잠시 바꾸고 싶을 때 사용한다.
  • 비상수 지시 포인터를 상수 지시 포인터로 바꾸고자 할 때는 그냥 대입으로 끝난다. 캐스팅할 필요가 없다.
void main()
{
     char str[]="string";
     const char *c1=str;
     char *c2;
  
     c2=const_cast<char *>(c1);
     c2[0]='a';
     printf("%s\n",c2);
}

dynamic_cast

  • 업 캐스팅의 경우 static_cast와 마찬가지로 안전하다.
  • 다운 캐스팅을 할 때, 자식에게만 있느 멤버를 참조할 경우 문제가 생길 수 있는데, dynamic_cast는 이럴 경우 캐스팅을 허용하지 않고 NULL을 리턴하여 위험한 변환을 허가하지 않는다.
class Parent
{
public:
	virtual void PrintMe() { printf("I am Parent\n"); }
};

class Child : public Parent
{
private:
	int num;

public:
	Child(int anum = 1234) : num(anum) { }
	virtual void PrintMe() { printf("I am Child\n"); }
	void PrintNum() { printf("Hello Child=%d\n", num); }
};

void main()
{
	Parent P, *pP, *pP2;
	Child C, *pC, *pC2;
	pP = &P;
	pC = &C;

	pP2 = dynamic_cast<Parent *>(pC);       // 업 캐스팅-항상 안전하다.
	pC2 = dynamic_cast<Child *>(pP2);       // pP2는 사실 Child를 가리키므로 가능. Child가 아니라면 불가능.
	printf("pC2 = %p\n", pC2);
	pC2 = dynamic_cast<Child *>(pP);        // 캐스팅 불가능. NULL 리턴.
	printf("pC2 = %p\n", pC2);
}
  • 포인터(a)의 타입과 대입하려는 포인터(b)가 실제로 가리키고 있는 객체의 타입이 일치한다면 다운 캐스팅을 하고, 그렇지 않을 경우 캐스팅을 거부한다.
  • 다운 캐스팅할 때, static_cast는 무조건 변환을 허가하지만, dynamic_cast는 실행 중에 타입을 점검하여 안전한 캐스팅만 허가한다는 점에서 다르다.

Clone this wiki locally