C++/문법

Casting

전용 2023. 10. 25. 20:58

Casting(캐스팅)이란?

변수의 데이터 타입을 다른 데이터 타입으로 변경하는 것

ex) Int → float

C++의 형변환

1. 묵시적 형변환 (Implicit type conversion)

int main()
{
    // 1. 묵시적 캐스팅
    int a = 4;
    float b = 3.14;
    a = b;
    // 3 출력
    cout << a << endl;

    return 0;   
}

위의 코드는 int 로 선언된 변수 a에 float로 선언된 b를 할당한 후 출력하는 코드이다.

다른 코드의 추가 없이 데이터 타입이 다른 값을 할당했을 때 컴파일러가 자동으로 floatint로 바꾸어 할당하는데

이 것이 묵시적 형변환이다.

2. 명시적 형변환 (Explict type conversion)

int main()
{
    // 2. 명시적 캐스팅
    int a;
    float b = 3.14;
    a = (int)b;
    // 3 출력
    cout << a << endl;

    return 0;
}

위의 코드는 int 로 선언된 변수 a에 float로 선언된 b를 할당한 후 출력하는 코드이다.

묵시적 형변환과 다르게 할당할 변수 앞에 (int) 를 추가하여 어떠한 변수로 형변환 할 지 나타내주었다.

이 것이 명시적 형변환이다.

3. Cast Operator

명시적, 묵시적 형변환은 C/C++ 에서 공통으로 사용 가능한 형변환이다. C++ 에는 위의 두 가지 방법 외에도 Cast Operator를 사용하여

형변환을 할 수 있다.

3.1 static_cast

int main()
{
    // 3.1 static_cast
    // 문법 static_cast<변환할 데이터타입>(변환할 변수)
    // float인 a를 int인 b로 변경
    float a = 3.14;
    int b = static_cast<int>(a);
    // 3 출력
    cout << b << endl;

    Parent p;
    Child c;
    Parent* p_ptr;
    Child* c_ptr;

    // Parent 출력
    p = static_cast<Parent>(c);
    p.Say();

    // 불가능
    // c = static_cast<Child>(p);
    // c.Say();

    // Parent 출력
    p_ptr = static_cast<Parent*>(&c);
    p_ptr->Say();

    // Parent 출력
    p_ptr = static_cast<Child*>(&c);
    p_ptr->Say();

    // Child 출력
    c_ptr = static_cast<Child*>(&p);
    c_ptr->Say();

    return 0;
}

논리적으로 변경이 가능한 경우에만 변경을 허용하는 형변환이다.

정수와 실수, 열거형과 정수, 실수와 실수 등의 형변환이 가능하고 array → pointer, function → function pointer의 형변환도 가능하다.

상속관계에 있는 클래스의 포인터끼리도 형변환이 가능하다.

그러나 포인터를 다른 데이터 타입으로 변경하는 것은 불가능하다.

3.2 const_cast

int main()
{
    // 3.2 const_cast
    // 문법 const_cast<변환할 타입>(변환 대상)
    // 포인터 및 참조형에서만 사용 가능
    
    const int * a = new int(10);
    int *b;

    // 10 출력
    cout << *a << endl;

    b = const_cast<int*>(a);
    *b = 20;

    // 20 출력
    cout << *a << endl;

    char str[] = "CPP_STUDY";
    const char *ptr = str;

    //CPP_STUDY 출력
    cout << str << endl; 

    char *c = const_cast<char*>(ptr);
    c[0] = 'D';

    // DPP_STUDY 출력
    cout << str << endl;

		const int num = 30;
    // 불가능
    //int num2 = const_cast<int>(num);
    return 0;
}

포인터 또는 참조형 변수의 const 키워드를 제거하는데 사용된다.

다른 형변환과 함수포인터는 불가능하다.

3.3 reinterpret_cast

int main()
{
    // 3.3 reinterpret_cast
    // 문법 reinterpret_cast<변환할 타입>(변환 대상) 
    // 임의의 포인터타입끼리 변환을 허용하는 캐스트 연산자
    // 정수형을 포인터로 변환할 수 있으나 이 때 정수값이 포인터의 절대주소로 대입
    
    // int -> int* 변수 a의 값을 절대주소로 받는 포인터 ptr1
    // 어떤 주소를 가리킬 지 모른다
    int a = 71234561;
    int *ptr1;
    ptr1 = reinterpret_cast<int*>(a);

    // int * -> char * 로 형변환
    // 컴파일러에 따라 다르게 나온다.
    int *ptr2 = &a;
    char *c;
    c = reinterpret_cast<char*>(ptr2);

    // 출력 안됨
    cout << *c << endl;
    // 1 출력 (컴파일러에 따라 다름)
    printf("%d\n", *c);

    //3. struct 내의 첫번째 int -> int *
    //struct cube에는 int 형 변수 하나만 존재 하므로,
    //ptr3은 int a변수의 시작점을 잘 가리키고 있습니다
    strData p;
    p.a = 20;
    int * ptr3;
    ptr3 = reinterpret_cast<int *>(&p);

    // 20 출력
    cout << *ptr3 << endl;
 
    return 0;
}

임의의 포인터 타입끼리 변환을 허용하는 캐스트 연산자이다.

정수형 데이터타입을 포인터 타입으로 변환할 수 있는데 이 때 변수에 할당되어있는 정수 값이

포인터 변수의 주소값으로 들어가기 때문에 위험하다.

다른 형태의 포인터로 변환하는 경우 결과 값이 컴파일러에 따라 다르게 나오거나 예상치 못한 값이

나올 수 있다.

3.4 dynamic_cast

int main()
{
    // 3.4 dynamic_cast
    // 문법 dynamic_cast<변환할 타입>(변환 대상)
    // Class의 포인터 또는 참조변수 간 형변환 시 안전하게 down casting을 하기 위해 사용한다.
    // 단, 부모 클래스에 virtual 함수가 존재해야 정상 작동한다.
 
    // Parent 출력
    Parent* ptr_p = new Child();

    // Child 출력
    Child* ptr_c;

    // Parent Say 출력
    ptr_p->Say();

    ptr_c = dynamic_cast<Child*>(ptr_p);

    if (ptr_p == nullptr)
    {
        cout << "Complie error" << endl;
    }
    // Child Say 출력
    ptr_c->Say();
    
    return 0;
}

부모 클래스의 포인터에서 자식 클래스의 포인터로 다운캐스트할 때 사용하는 캐스트연산자이다.

부모 클래스에 virtual 함수가 존재해야 정상 작동하며 런타임에 실제로 해당 타입이 다운캐스팅이

가능한지 검사하기 때문에 비용이 높은 캐스트 연산자이다.

성공할 경우 변환할 타입의 값을 return하며 실패할 경우 nullptr을 반환한다.

참조형 변수일 경우 bad_cast 처리가 되어 예외처리가 된다.


Uploaded by N2T