<개인공부>/[C++]

[C++] dynamic_cast (타입캐스트 연산자)

BlockDMask 2018. 7. 25. 20:13
반응형

안녕하세요. BlockDMask 입니다.

이번에는 C++의 네가지 타입캐스트 연산자
(static_cast, const_cast, reinterpret_cast, dynamic_cast) 중에서
마지막 dynamic_cast
에 대해서 알아보겠습니다.

 

1. dynamic_cast에 대해서


dynamic_cast는 safe downcasting(안전한 다운캐스팅)에 사용이 됩니다. (물론 upcasting에도 쓰입니다)

조금 쉽게 말씀 드리자면, 부모 클래스의 포인터에서 자식 클래스의 포인터로 다운 캐스팅 해주는 연산자 입니다.
(부모클래스의 포인터가 실제 무엇을 가리키고 있는지가 중요합니다)

하지만, 런타임 시간에 실제로 해당 타입이 다운 캐스팅이 가능한지 검사하기 때문에, 런타임 비용이 조금 높은 캐스트 연산자 입니다.

dynamic_case<new_type>(expression)

dynamic_case<바꾸려는 새로운 타입>(대상)

ex) dynamic_cast<childClass*>(pParent*);

성공할 경우 : new_type의 value를 return 합니다.

실패할 경우(new_type = pointer) : null pointer

실패할 경우(new_type = reference) : bad_cast (exception 처리됩니다.)

 

 

2. C++ dynamic_cast 예제(1) 다운 캐스팅


"부모클래스의 생성자로 생성되었고 부모 포인터가 가리키고 있는 클래스"를 자식클래스 포인터로 형변환(dynamic_cast) 할때.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
using namespace std;
class Blog
{
public:
    Blog() { cout << "Blog()\n"; };
    virtual ~Blog() { cout << "~Blog()\n"; };
 
    void Show()
    {
        cout << "This is Blog Class\n";
    }
};
 
class Tistory : public Blog
{
public:
    Tistory() { cout << "Tistory()\n"; };
    virtual ~Tistory() { cout << "~Tistory()\n"; };
 
    void Show()
    {
        cout << "This is Tistory Class\n";
    }
};
 
int main(void)
{
    Blog* pBlog = new Blog();
 
    //출력됩니다.
    pBlog->Show();
 
    Tistory* pTistory = dynamic_cast<Tistory*>(pBlog);
    if (pTistory == nullptr)
    {
        //티스토리 클래스의 포인터가 nullptr이 나올떄.
        cout << "Runtime Error\n";
    }
    else
    {
        pTistory->Show();
    }
    
    delete pBlog;
    system("pause");
    return 0;
}
cs

결과 : runtime error 가 발생하게 됩니다.
이유 : new Blog()를 통해서 생성 되었기 때문에, 당연하게도 Tistory 생성자는 불리지 않았습니다.
생성자도 불리지 않았는데, 무슨 해당 타입으로 포인터를 만들까요.
 

 

 

 

 

 

 

3. C++ dynamic_cast 예제(2) 다운 캐스팅


"자식클래스의 생성자로 생성되었고 부모클래스 포인터가 가리키고 있는 클래스"를 자식클래스로 형변환(dynamic_cast) 할때

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
using namespace std;
class Blog
{
public:
    Blog() { cout << "Blog()\n"; };
    virtual ~Blog() { cout << "~Blog()\n"; };
 
    void Show()
    {
        cout << "This is Blog Class\n";
    }
};
 
class Tistory : public Blog
{
public:
    Tistory() { cout << "Tistory()\n"; };
    virtual ~Tistory() { cout << "~Tistory()\n"; };
 
    void Show()
    {
        cout << "This is Tistory Class\n";
    }
};
 
int main(void)
{
    Blog* pBlog = new Tistory();
 
    //출력됩니다.
    pBlog->Show();
 
    Tistory* pTistory = dynamic_cast<Tistory*>(pBlog);
    if (pTistory == nullptr)
    {
        //티스토리 클래스의 포인터가 nullptr이 나올떄.
        cout << "Runtime Error\n";
    }
    else
    {
        pTistory->Show();
    }
    
    delete pBlog;
    system("pause");
    return 0;
}
cs

결과 : 자식클래스의 포인터로 다운캐스팅이 잘 됩니다.
바뀐부분은 Blog* pBlog = new Tistory(); 요기 하나 뿐 입니다. 

중요한것 1) 부모 클래스(Blog)의 포인터로 자식클래스(Tistory)를 가리킬 수 있습니다.
중요한것 2) pBlog->Show()는 실제 pBlog가 가리키는 클래스는 본인의 자식클래스인 Tistory 클래스 이지만, virtual로 선언되어있지 않기 때문에 pBlog가 가지고 올 수 있는 것은 본인의 Show() 함수 입니다.

제일 중요) pBlog가 실제 가리키는 클래스(new를 통해 생긴 클래스)는 자기 자식인 Tistory 클래스 이므로 dynamic_cast를 통해서 다운캐스팅이 가능합니다.

 

 

3. C++ dynamic_cast 예제(3) 업 캐스팅


"자식클래스의 생성자로 생성되었고 자식클래스 포인터가 가리키고 있는 클래스"를 부모클래스로 형변환 할때는 dynamic_cast를 사용하지 않고 static_cast를 사용합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
using namespace std;
class Blog
{
public:
    Blog() { cout << "Blog()\n"; };
    virtual ~Blog() { cout << "~Blog()\n"; };
 
    void Show()
    {
        cout << "This is Blog Class\n";
    }
};
 
class Tistory : public Blog
{
public:
    Tistory() { cout << "Tistory()\n"; };
    virtual ~Tistory() { cout << "~Tistory()\n"; };
 
    void Show()
    {
        cout << "This is Tistory Class\n";
    }
};
 
int main(void)
{
    Tistory* pTistory = new Tistory();
 
    //출력됩니다.
    pTistory->Show();
 
    Blog* pBlog = static_cast<Blog*>(pTistory);
   pBlog->Show();
    
    delete pTistory;
    system("pause");
    return 0;
}
cs

결과 : 부모클래스로 업캐스팅할때는 static_cast를 사용합니다.
pBloc->show를 보면 부모클래스의 "This is Blog Class"가 불리는 것을 볼 수 있습니다.

읽어주셔서 감사합니다.

반응형