앞서 static_cast에 이어서 나머지 캐스팅 연산자에 대한 내용입니다. conast_cast와 dynamic_cast는 사용 빈도수가 높지 않습니다. 그래도 중요한 포인트는 기억해 두어야 합니다.
const_cast
이름으로 유추해 보면 상수를 상수가 아닌 수로 또는 그 반대로 바꾸는 경우에 사용할 듯 싶네요. 그런데 이름 그대로 이해하면 안됩니다. 앞서 살펴본 static_cast의 경우 상수변수의 상수성을 없애는 용도로 사용했었습니다. 그렇다면 const_cast라는 것을 굳이 둘 필요가 없겠죠. 바로 const_cast은 포인터나 참조로만 캐스팅이 가능합니다. 이 때에는 상수성을 주거나 또는 상수성을 없앴 수만 있습니다.
예를 들어 보면...
num이라는 정수형 상수와 이에 대한 상수 지시 포인터 ci가 선언되었죠. 여기서 ci의 상수성을 없애는 작업이 const_cast<int*>입니다. ci의 타입에서 const만 제거되었죠? 즉 여기서 "상수성을 없앤 작업"의 의미는 정수 상수를 가리키는 포인터에서 정수를 가리키는 포인터로 변경한다는 의미입니다.
참조의 경우 역시 마찬가지 입니다.
이번에는 상수성을 없앤 경우와 추가한 경우입니다. 사실 참조의 경우 위 예제는 의미가 없습니다. 왜냐면 정수를 포인터가 아닌 참조로 전달하는 경우는 단순히 값만 대입되기 때문에 상수가 되입되든 상수가 아닌 수가 대입되든 상관없습니다. 단지 참조로 캐스팅이 허용된다는 것으로 이해하면 됩니다.
C언어에서 정수가 아닌 문자열의 경우는 const인지 아닌지에 따라서 대입 여부가 엄격히 통제됩니다. 왜냐면 기본적으로 C언어에서는 문자열을 포인터로 다루기 때문이죠. 뭐 C++역시 C언어 문법을 따라가기 때문에 그냥 C언어라고 표현한겁니다.
그럼 문자열의 예를 들어보겠습니다.
위 캐스팅은 가능하지만 위험한 캐스팅입니다.(런타입 에러) 문자열에 대해서 char*타입으로 선언한 경우 해당 문자열은 코드영역에 포함됩니다. 즉 "hello"라는 문자열은 프로그램이 실행된 후에 변경해서는 안되는 영역에 들어가 있기 때문에 위와 같이 char*로 캐스팅하면 안됩니다. 이렇게 캐스팅을 해버리면 변경 시도에 대한 에러는 안뜹니다. 다만 실행 시에 에러가 나겠죠. 변경하지 마세요..
변경 가능한 문자열을 만들려면 다음처럼 배열에 넣어서 선언해야 합니다. 우선은 const로 선언을 했습니다.
이렇게 하면 str1을 통해서는 문자열를 변경할 수 없지만 temp를 통해서는 해당 문자열을 변경할 수 있습니다.
만약 반대로 변경 가능한 문자열에 상수성을 주고 싶다면 const_cast<const char*>로 캐스팅 하면 됩니다.
마지막으로 주의할 점은 const_cast는 type을 변경할 수는 없다는 점입니다. 다시말해 포인터 타입 또는 참조 타입으로 변경할 때 기본 타입은 그대로 두고 상수성의 유무만 변경할 수 있습니다.