C++의
4가지 캐스트 연산자에 대한 이야기다.
이번은 그중에서
const_cast 에 대해서 이야기한다.
나머지도 각각 한 번에 하나씩 적어보도록 하겠다.
const_cast 는 포인터 또는 참조형의 상수성(const)을 제거하는 데 사용된다.
다른 용도로는 사용하지 못하며 다른 캐스트 연산자는 상수성을 제거할 수 없다.
이렇게 정해진 용도가 명확한 것이 C++ 캐스트 연산자의 특징 중 하나다.
용도가 명확한 만큼 별도의 주석 없이 코드만으로 작성자의 의도가 쉽게 파악된다.
volatile 한정자를 제거하는 데도 사용된다고 하는데 사용해본 적이 없다.
특정 스레드나 루프에서 휘발성을 제거하여 컴파일러에게 최적화를 해도 된다고 알려주는 정도로 사용할 듯싶다.
- const_cast 사용[예제 1]
const int* pConstInt = new int( 10 );
int* pInt = const_cast<int*>( pConstInt );
*pInt = 200;
cout << *pConstInt << endl;
위의 [예제 1] 에서 pConstInt 의 상수성은 제거되면서 pInt 로 포인터가 복사된다.
상수성이 없는 pInt 는 포인터의 대상 값을 아무런 문제없이 변경할 수 있다.
단순 설명을 위한 예가 아닌 const_cast 가 자주 사용되는 하나의 예를 보이고 싶은데 막상 생각나는 게 별로 없다.
[예제 2]
class ExternalClass
{
public :
int GetValue( void ) { return Value; }
void SetValue( int _Value ) { Value = _Value; }
private :
int Value;
};
class TestClass
{
public :
bool IsZero( const ExternalClass& _rObj ) const
{
if ( const_cast<ExternalClass&>( _rObj ).GetValue() == 0 ) return true;
return false;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
ExternalClass ValueObj;
ValueObj.SetValue( 100 );
TestClass TestObj;
if ( TestObj.IsZero( ValueObj ) )
cout << "Zero" << endl;
else
cout << "Nonzero" << endl;
return 0;
}
예제치고는 길지만 [예제 3] 에 별다른 내용은 없다.
가끔 외부 라이브러리를 사용하는 경우 'ExternalClass' 처럼 모두 비상수 메서드로 제공 될 경우가 있다.
이때 사용하는 측에서 'bool IsZero( const ExternalClass& _rObj ) const' 처럼 상수 메서드를 만들어서 사용할 경우에 const_cast 가 필요하다.
const_cast 없이 'const ExternalClass& _rObj'로 매개변수를 받아서는 'ExternalClass'의 어떤 메서드도 호출할 수 없기 때문이다.
- 주의 사항
const_cast는 포인터의 상수성을 제거하는 데 사용된다고 되어 있다.
[예제 3]
const int ConstInt = 10;
int* pInt = const_cast<int*>( &ConstInt );
*pInt = 200;
cout << ConstInt << endl;
위의 [예제 3] 에서 ConstInt의 값은 변하지 않는다.
여기서는 단순히 값이 변하지 않았지만 어떤 동작을 보일지는 미정이다.
상수 객체의 상수성을 제거해서 캐스팅은 가능해도 상수 객체 자체의 내용을 바꿀 수는 없다.
[예제 1] 의 1번째 라인 'const int* pConstInt = new int( 10 );' 에서 pConstInt는 상수 포인터다.
하지만, 포인터가 가리키는 대상은 상수 객체가 아닌 비상수 int 변수일 뿐이다.
- 더하기
블로그에 올렸던 글입니다.