C++캐스팅
FrontPage|FindPage|TitleIndex|RecentChanges|UserPreferences E D R S I M H RSS

그동안 모호했던(저혼자 모호.. ㅜ_ㅜ) C++의 각종 cast들에 대해서 정리해보았습니다.

C++은 C-style-cast의 문제점을 보완하기 위해 다음과 같은 4가지 cast를 지원합니다.

static_cast<>() dynamic_cast<>() const_cast<>() reinterpret_cast<>()

<> 안에 타입이 들어가고 캐스팅 하려는 타입은 반드시 뒤에 괄호로 묶어주어야 합니다.

============================================================================ =========== static_cast 는 컴파일 타임에 casting 타입을 알 수 있는 타입들을 casting 할 때 사용합니다. dynamic_cast 는 hierarchy 가 있는 class 들 사이를 오갈 때(up, down casting 모두) 사용합니다. const_cast 는 타입의 const 성을 없앨 때 사용합니다. reinterpret_cast 는 별 관계 없는 타입들 간에 casting을 해야 할 때 타입만 바꿔주는데 사용합니다. ============================================================================ ===========

C-style-cast == static_cast + reinterpret_cast 정도로 보시면 됩니다.

dynamic_cast 는 반드시 vtable(virtual function table)이 존재해야 합니다. dynamic_cast 는 vtable을 차례로 뒤지기 때문에 실행시간이 O(N) 입니다.

static_cast 는 hierarchy가 존재하는 class 들 간에도 upcasting은 가능합니다. (컴파일 타임에 알 수 있으므로 당연합니다.) 이를 언급하는 것은 hierarchy가 존재할 때 무조건 dynamic_cast를 사용하는 우를 범하지 않기 위함입니다. downcasting은 당연히 dynamic_cast를 사용해야 합니다.

아래는 예제 프로그램입니다. 심심하실 때 한번씩 돌려보시길.. :)

============================================================================ ===========

#include <stdio.h>

class Root {
public:
virtual void rootx() = 0;
};
class A : public Root {
public:
virtual void fn() = 0;
};

class B : public Root {
public:
virtual void fx() = 0;
};

class Foo : public A, public B
{
    virtual void zz() { }
    void rootx() { }
    void fn() {
     }
     void fx() {
     }
};

int main()
{
    Foo *p = new Foo();
    B *z = (B *)p;
    Root *q = static_cast<Root *>(static_cast<B *>(p));
    Root *r = dynamic_cast<Root *>(dynamic_cast<B *>(p));
    Root *x = (Root *)(((B *)(p)));

    printf("foo = %p\n", p);
    printf("(A *) = %p\n", (A *)p);
    printf("(b *) = %p\n", (B *)p);
    printf("static_cast<A *>(Foo *) = %p\n", static_cast<A *>(p));
    printf("static_cast<B *>(Foo *) = %p\n", static_cast<B *>(p));

    void *v = static_cast<void *>(p);
    printf("static_cast<A *>(void *) = %p\n", static_cast<A *>(v));
    printf("static_cast<B *>(void *) = %p\n", static_cast<B *>(v));

    printf("dynamic_cast<A *>(Foo *) = %p\n", dynamic_cast<A *>(p));
    printf("dynamic_cast<B *>(Foo *) = %p\n", dynamic_cast<B *>(p));

    printf("reinterpret<A *>(Foo *) = %p\n", reinterpret_cast<A *>(p));
    printf("reinterpret<B *>(Foo *) = %p\n", reinterpret_cast<B *>(p));

    printf("q = %p\n", q);
    printf("r = %p\n", r);
    printf("x = %p\n", x);
    //printf("(Foo *) = %p\n", (Foo *)q);
    //printf("static<Foo *> = %p\n", static_cast<Foo *>(q));
    printf("dynamic_cast<Foo *>(Root *) = %p\n", dynamic_cast<Foo *>(q));
    printf("reinterpret_cast<Foo *>(Root *) = %p\n", reinterpret_cast<Foo
*>(q));

    printf("dynamic_cast<A *>(B *) = %p\n", dynamic_cast<A *>(z));
}

다른 분 코멘트

static_cast는 compile time에 주어진 type을 통해 compile time에 결정할 수 있는 casting을 수행할 경우 사용하고,

반면, dynamic_cast는 compile time에 주어진 type이 아니라 runtime에 casting당하는 object의 실제 type 정보 (vtable 이겠죠)를 이용해서 casting을 수행한다고 말해야겠습니다. 따라서, up/downcast는 물론 sibling으로도 casting 가능합니다. dynamic_cast는 주로 polymorphism의 용도로 쓰입니다.

reinterpret_cast는 compiler의 impl-dependent한 cast이고 따라서 non-portable하므로, 가급적 자제해야합니다. ^^;

const_cast도 원래 constant가 아닌 storage를 가지는 data를 const_cast로 사용해서는 안됩니다.


dynamic_cast, reinterpret_cast, const_cast 등을 사용하기 전에 cast를 유발하게 된 원인이 무엇인지, design에 문제가 있는 것은 아닌지 검토하는 습관이 필요합니다.

EditText|FindPage|DeletePage|LikePages| Valid XHTML 1.0! Valid CSS! powered by MoniWiki