페이지

2015년 1월 4일 일요일

Casting은 최대한 쓰지말자. 쓸일이 있으면 C++ Style Casting 을 사용하자.

* 다른 방법이 가능하다면 캐스팅은 피하십시오. 특히 수행 성능에 민감한 코드에서 dynamic_cast는 몇 번이고 다시 생각하십시오. 설계중에 캐스팅이 필요해졌다면, 캐스팅을 쓰지 않는 다른 방법을 시도해 보십시오.

* 캐스팅이 어쩔 수 없이 필요하다면, 함수 안에 숨길 수 있도록 해 보십시오. 이렇게 하면 최소한 사용자는 자신의 코드에 캐스팅을 넣지 않고 이 함수를 호출할 수 있게 됩니다.

* C Style 캐스팅을 쓰려거든 C++ Style 캐스팅을 선호하십시오. 발견하기도 쉽고, 설계자가 어떤 역할을 의도했는지가 더 자세하게 드러납니다.

우리가 흔히 사용하는 (T) 표현식 은 C Stlye 캐스팅이다.

C++ Style 캐스팅은 아래와 같이 4가지가 있다.

static_cast<T>( 표현식 )
암시적 변환을 강제로 진행할 때 사용한다. C Style의 캐스팅은 대부분 static_cast로 바꾸면 된다. int를 double로 바꾸는 경우에도 사용이 가능하며, void* 를 일반 Pointer로 바꾼다던지, 기본 클래스의 Pointer를 자식 클래스의 Pointer로 바꾸는 경우에도 사용된다.

const_cast<T>( 표현식 )
상수 객체를 비상수 객체로 캐스팅한다.

dynamic_cast<T>( 표현식 )
상속 관계에 있는 객체간의 Downcasting을 할때 사용한다. 실행속도가 많이 느리므로 최대한 사용을 피해야 하며, 부모 Class에서 사용할 함수에 대해서 virtual 로 선언을 하면 dynamic_cast 를 피할수 있다.

reinterpret_cast<T>( 표현식 )
Pointer 를 int로 바꾸는 등의 하부 수준 캐스팅을 위해 만들어졌으나, 구현환경에 의존적이다. 거의 사용하지 않는다.

캐스팅을 쓰면 런타임시에 실행되는 코드가 만들어지는 경우가 많다. 그래서 예상치 못한 런타임 오류가 발생할 확률이 크다.

class Base {
    virtual void OnResize() { ... }
};

class Derived : public Base {
    virtual void OnResize() {
        static_cast<Base>(*this).onResize();     // 동작이 되지 않는 Code
        Base::OnResize();                        // 정상적으로 동작하는 Code
    };
};

Derived d;
Base *pd = &d;

위의 Code에서 당연히 pd는 오직 한개의 주소로 d 의 주소를 가질 것으로 생각을 하겠지만, Base* 로 가리킬 때의 주소, Derived* 로 가리킬 때의 주소 이렇게 2개를 가리키는 경우가 많다. 다중 상속이라면 당연히 이렇게 되어야 하지만, 아닌 경우에도 이런 현상이 발생한다. 플렛폼마다 서로 다른 결과를 낼 수가 있기 때문에 위험하지만, 대부분의 프로그래머들이 그 사실을 알지 못한다.

부모 Class의 함수를 호출 할 경우에도  static_cast를 이용하여 호출하면, Base Class의 사본을 다른 Memory에 만들어서 실행을 하기 때문에 원하는 동작을 하지 않는다. Base:: 와 같은 방법으로 실행해야 한다.

댓글 없음:

댓글 쓰기