언어 자료구조 알고리즘/디딤돌 C++

[C++] 38. C++에서의 형 변환

언제나휴일 2016. 4. 25. 00:49
반응형


C++에서의 형 변환


이번에는 C++언어에서 제공하는 형 변환에 관해 살펴보기로 해요.

 

이 부분은 OOP 특징은 아니지만 앞에서 dynamic_cast를 사용하는 방법을 소개하여 다른 형 변환도 알아보려는 거예요.

 

먼저 C++ 언어에서도 강제 형변환(명시적 형변환이라고도 부름)을 제공하고 있습니다. 하지만 강제 형변환은 잘못 사용하면 심각한 버그를 유발할 수 있습니다.

 

다음은 서로 관련이 없는 Man 클래스와 Student 클래스를 정의한 후에 강제 형변환을 사용하는 예제입니다. 컴파일 오류는 발생하지 않지만 프로그램 동작 중에 버그로 런 타임 오류가 발생할 수 있습니다.


Program.cpp


//강제 형 변환이 갖는 위험 요소

#include <iostream>

#include <string>

using namespace std;

 

class Man

{       

    string name;

public:

    Man(string name)

    {       

        this->name = name;

    }

    void View()const

    {

        cout<<"이름:"<<name<<endl;

    }

};

 

 

 

class Student

{

    int num;

    string name;

public:

    Student(int num, string name)

    {

        this->num = num;

        this->name = name;

    }

    void View()const

    {

        cout<<"번호:"<<num<<"이름:"<<name<<endl;

    }

};

 

int main()

{

    Student *stu = new Student(30,"홍길동");

    Man *man = (Man *)stu; //강제 형변환

    man->View();

    delete stu;

    return 0;

}

강제 형 변환이 갖는 위험 요소

C++에서는 보다 엄격하게 형 변환할 수 있는 방법을 제공하고 있습니다. 앞에서 다루었던 dynamic_cast는 일반화 관계에서 하향 캐스팅을 제공했었죠.

 

이 외에 static_cast, const_cast, reinterpret_cast를 제공하고 있습니다.

 

먼저 static_cast C언어의 강제 형변환과 유사합니다. 기반 클래스와 파생 클래스 사이의 형 변환 뿐만 아니라 기본 자료 형식 사이에서도 형 변환을 할 수 있습니다. 하지만 이에 관한 모든 책임은 개발자에게 있다는 것을 잊지 마세요.

 

다음은 하향 캐스팅을 dynamic_cast를 이용하지 않고 static_cast를 이용하였습니다. dynamic_cast를 사용하려면 가상 메서드를 갖고 있어야 하지만 static_cast는 가상 메서드를 갖고 있지 않아도 가능합니다.


Program.cpp


//static_cast

#include <iostream>

#include <string>

using namespace std;

class Man

{       

    string name;

public:

    Man(string name)

    {       

        this->name = name;

    }

    void View()const

    {

        cout<<"이름:"<<name<<endl;

    }

};

 

class Student:public Man

{

    int num;

    string name;

public:

    Student(int num, string name):Man(name)

    {

        this->num = num;

        this->name = name;

    }

    void View()const

    {

        cout<<"번호:"<<num<<"이름:"<<name<<endl;

    }

    void Study()

    {

        cout<<name<<" 공부하다."<<endl;

    }

};

 

int main()

{

    Man *man = new Student(30,"홍길동");

    Student *stu = static_cast<Student *>(man);

    stu->Study();

    delete man;

    return 0;

}

 

▷ 실행 결과

홍길동 공부하다.

 

다음은 기본 형식 사이에 static_cast를 사용한 예제입니다.


Program.cpp


//기본 형식 간에 static_cast

#include <iostream>

using namespace std;

 

int main()

{

    int a = 3;

    double d;

 

    d = static_cast<double>(a);

    cout<<d<<endl;

    return 0;

}

 

▷ 실행 결과

3

 

하지만 언제나 static_cast를 할 수는 없습니다. 예를 들어 string 형식과 int 형식 사이에서는 static_cast를 할 수 없습니다.


Program.cpp


//static_cast 를 할 수 없는 예

#include <iostream>

#include <string>

using namespace std;

 

int main()

{

    int a = 3;

    string name;

 

    name = static_cast<string>(a);//형 변환 오류

    cout<<name<<endl;

    return 0;

}

static_cast는 다양한 형태에서 형 변환을 할 수 있지만 모든 책임은 개발자의 몫임을 항상 잊지 마세요.

 

이번에는 const_cast를 알아봅시다.

 

const 포인터 변수는 가리키는 값을 변경할 수 없죠. const_cast const 포인터 변수가 가리키는 값을 변경할 수 있게 형 변환합니다. 만약 값을 변경하지 않겠다는 의미로 const 포인터 변수를 입력 인자로 받은 후에 const_cast로 값을 변경할 수 있다는 것입니다. 이러한 사용은 프로그램의 신뢰성이 떨어질 수 있습니다.


Program.cpp


//const_cast

#include <iostream>

using namespace std;

 

void View(const int *input)

{   

 

    int *temp = const_cast<int *>(input);   

 

    *temp = 9;

    cout<<"=== 가리키는 값 출력 ==="<<endl;

    cout<<"*temp:"<<*temp<<endl;

    cout<<"*input:"<<*input<<endl;   

}

int main()

{

    int value = 10;

 

    View(&value);

    return 0;

}

 

▷ 실행 결과

=== 가리키는 값 출력 ===

*temp:9

*input:9

 

마지막으로 reinterpret_cast를 알아봅시다. reinterpret_cast는 강제 형변환처럼 거의 모든 형 변환을 가능하게 해 줍니다. 예를 들어 flat * int *로 형 변환을 요청하는 것을 허용합니다. 이러한 변환에서는 형 변환한 곳의 값을 float 형식이 아닌 int이라고 해석하여 값을 출력합니다.

 

다음은 float 형식 변수 -12.625가 메모리에 어떻게 기록하는지 확인하기 위해 reinterpret_cast를 사용한 예제 코드입니다.


Program.cpp


//reinterpret_cast

#include <iostream>

#include <iomanip>

#include <string>

 

using namespace std;

 

int main()

{

   

    float f=-12.625;

    float *pf = &f;

    int *a;

 

    a = reinterpret_cast<int *>(pf);

    cout<<hex<<(*a)<<endl;

    return 0;

}

 

▷ 실행 결과

c14a0000

 

dynamic_cast는 다형성이 갖는 단점을 해결하기 위해 사용하지만 다른 형 변환은 극약 처방이 필요한 응급 상황이 아니면 사용을 자제해 주세요.

반응형