-
Notifications
You must be signed in to change notification settings - Fork 1
Cast
mooneegee edited this page Nov 19, 2013
·
2 revisions
- 형을 변환하는 것
- static_cast, reinterpret_cast, const_cast, dynamic_cast가 있다.
- 서로 유사성이 없는 자료형 간에도 형변환이 가능하다.
- 편리하게 사용할 수 있다는 장점은 있지만 엄격하지 못한 형변환으로 실수가 발생할 수도 있다.
- 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은 사용하지 않는 것이 좋다.
- 캐스팅이 묵시적으로 일어나는 경우 이를 명시적으로 형변환하겠다라고 분명히 해주는 용도로 사용된다.
- 논리적으로 변환 가능한 타입으로만 변환할 수 있다.
- 클래스의 경우 상속관계를 따져보고 변환하며 상호호환 관계가 아니면 컴파일 에러를 발생시켜 개발자가 에러를 발견하기 쉽게 해준다.
- 대부분 이 캐스트를 사용한다.
- 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);
- 위의 코드는 다운 캐스팅이므로 위험하다.
- 다운 캐스팅 - 자식 클래스로 부모 클래스를 캐스팅하는 경우(부모 객체가 자식 클래스의 모든 멤버를 가지고 있다고 확신할 수 있는가? 없다.)
- 임의의 포인터 타입까리 변환을 허용하는 캐스팅 연산자이다.
- 강력한 만큼 위험도 크다.
- 강제 변환이므로 안전하지 않고 전적으로 개발자가 책임지고 관리해야 한다.(사용하지 않는 것이 답인듯 하다.)
int *pi; char *pc; pi = reinterpret_cast<int *>(12345678); pc = reinterpret_cast<char *>(pi);
- 이 연산자는 포인터 타입 간의 변환이나 포인터와 수치형 데이터의 변환에만 사용할 수 있다.
- 기본 타입들끼리의 변환에는 사용할 수 없다.(정수형->실수형 불가능)
- 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);
}
- 업 캐스팅의 경우 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는 실행 중에 타입을 점검하여 안전한 캐스팅만 허가한다는 점에서 다르다.