Notice
Recent Posts
Recent Comments
Link
«   2026/05   »
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
Archives
Today
Total
관리 메뉴

로또

Cast 본문

언어

Cast

아롱로또 2023. 11. 8. 03:32

작성 이유

C에서 사용하던 cast 대신 C++에서 사용 가능한 cast 종류를 알고 사용하기 위해 정리한다.

 

묵시적 형변환 (Implicit Type Casting)

정의

컴파일러에 의해 자동으로 변수의 Type이 변경되는 것.

표현 범위가 좁은 데이터 타입에서 넓은 데이터 타입으로의 변환만 가능하다.

예제

double d = 10; // 좁은 데이터 타입(int)인 i
int i = 4; // 넓은 데이터 타입(double)인 d
cout << d/i << endl; // 2.5

위 코드는 d / i의 연산을 위해 int -> double로 묵시적 형변환이 발생하였다.


 

명시적 형변환 (Explicit Type Casting)

정의

사용자가 직접 변수의 Type을 변경하는 것. 

묵시적 형변환과 달리 표현 범위가 넓은 데이터 타입에서 좁은 데이터 타입으로도 변환이 이루어질 수 있다.

예제

double d = 10;
int i = 4;
cout << (int)d/i << endl; // 2

위 코드는 d / i 연산을 할 때, double type인 변수 d를 int type으로 명시적 캐스팅하였다.

때문에 int type간 연산이 발생할 것이고 결과값 또한 double type인 2.5가 아닌 int type인 2를 가진다.


C++ Casting

C++에서는 위에서 예시로 든 C Style Casting 외에 아래와 같은 4가지 Cast 연산자를 지원한다.

  • static_cast
  • dynamic_cast
  • const_cast
  • reinterpret_cast

static_cast와 dynamic_cast, reinterpret_cast 연산자를 설명하기 위해 다음과 같은 클래스를 사용할 것이다.

class Animal {
public:
    virtual void sound(){ cout << "Animal Animal" << endl; }
};
class Dog : public Animal{
public:
    void sound() { cout << "Bow Bow" << endl; }
};

class Cat : public Animal {
public:
    void sound() { cout << "Meow Meow" << endl; }
};

 


static_cast

구문

static_cast <type-id> ( expression )

정의

Compile Time에 type cast에 대한 오류를 검사한다.

논리적으로 변환 가능한 타입에 대해 cast를 수행한다.

  • 실수와 정수, 열거형과 정수형, 실수와 실수 사이의 변환
  • array -> pointer 변환
  • function -> function pointer 변환

포인터 타입을 다른 타입으로 변환하는 것은 Compile Error를 발생시키며 허용하지 않지만 상속 관계에 있는 포인터 간에는 변환이 가능하다. downcast 시에는 unsafe하게 동작할 수 있다.

예제

int main() {
    Cat cat; // Cat 객체 생성

    Animal* p_animal = static_cast<Animal*>(&cat); // Animal과 Cat은 상속 관계, Up Casting
    p_animal->sound(); // Meow Meow

    Dog* p_dog = static_cast<Dog*>(&cat); // 상속 관계가 아닌 클래스 간 사용 시 컴파일 에러 발생.
    // p_dog->sound();

    return 0;
}

 

 

논리적으로 변환 불가능한 타입에 대해 static_cast 사용 시 컴파일 에러 발생

 


dynamic_cast

구문

dynamic_cast < type-id > ( expression )

정의

안전한 다운 캐스팅에 사용된다. 기본 클래스의 포인터에서 파생 클래스의 포인터로 다운 캐스팅해준다.

RunTime에 해당 Type이 다운 캐스팅 가능한 지 검사(RTTI)하므로 비용이 비싼 Cast 연산자이다.

성공할 경우, type-id의 value를 return한다.

실패할 경우 nullptr를 return하거나 exception이 발생한다.

예제

다운 캐스팅이 불가능한 경우

int main() {
    Animal* p_animal = new Animal();

    Cat* p_cat = dynamic_cast<Cat*>(p_animal);
    if(p_cat == nullptr){ cout << "nullptr" << endl; }
    else{ p_cat->sound(); }
    return 0;
}

실행 결과

 

p_animal은 기본 클래스인 Animal 생성자를 사용해 생성된 Animal 객체를 가리킨다.

이 때, p_animal은 Cat에 대한 정보를 전혀 갖고 있지 않으므로(Cat 생성자가 호출되지 않음) dynamic_cast 연산자는 nullptr를 반환한다.

 

다운 캐스팅이 가능한 경우

int main() {
    Animal* p_animal = new Cat();

    Cat* p_cat = dynamic_cast<Cat*>(p_animal);
    if(p_cat == nullptr){ cout << "nullptr" << endl; }
    else{ p_cat->sound(); }
    return 0;
}

 

실행 결과

 

1과는 달리 p_animal은 파생 클래스인 Cat 생성자를 사용해 생성된 Cat 객체를 가리킨다.

p_animal은 Cat에 대한 정보를 갖고 있으므로(Cat 생성자 사용) dynamic_cast 연산자는 올바르게 실행된다.

 


const_cast

구문

const_cast <type-id> (expression)

정의

포인터 또는 참조형의 const keyword를 제거하여 수정 가능하게 만든다.

예제

int main() {
    int value = 100;
    const int* c_ptr = &value;
    *c_ptr = 200; // 컴파일 에러 발생
}

 

컴파일 에러 발생

 

위 코드에서 c_ptr은 const int*로 상수성을 가져, c_ptr을 사용해 변수 value의 값을 변경할 수 없다. 위 사진처럼 상수에 대입 연산을 실행함으로 인해 컴파일 오류가 발생하는 모습을 볼 수 있다.

 

int main() {
    int value = 100;
    const int* c_ptr = &value;
    
    cout << "before: " << *c_ptr << endl;
    int* ptr = const_cast<int*>(c_ptr);
    *ptr = 200;
    cout << "after: " << *c_ptr << endl;
}

컴파일 및 실행 결과

 

이번에는 const_cast를 사용해 상수성을 제거한 후, ptr 변수를 이용해 value 변수에 접근, 값을 변경하였다. 실제로 결과값을 확인해보면 c_ptr가 가리키는 값이 100에서 200으로 변경된 것을 확인할 수 있다.


reinterpret_cast

구문

reinterpret_cast < type-id > ( expression )

정의

포인터가 다른 포인터 형식으로 변환될 수 있도록 한다. 또한 정수 타입이 포인터 타입으로, 포인터 타입이 정수 타입으로도 변환될 수도 있다. 즉, 자유로운 cast 연산이 가능하다.

형변환이 성공적으로 이루어지게 된다면 bit 단위로 값이 복사된다.

void *의 경우에도 사용이 가능하여 패킷 통신 시 자료를 받아올 때 사용할 수 있다고 한다.

예제

#include <iostream>
#include <string>
using namespace std;

class Animal {
public:
    virtual void sound(){ cout << "Animal Sound" << endl; }
};

class Dog : public Animal{
public:
    void sound() { cout << "Bow Bow" << endl; }
};

class Cat : public Animal {
public:
    void sound() { cout << "Meow Meow" << endl; }
};

int main() {
    Cat cat; // Cat 객체 생성

    Animal* p_animal = static_cast<Animal*>(&cat); // Animal과 Cat은 상속 관계, Up Casting
    p_animal->sound(); // Meow Meow

    Dog* p_dog = reinterpret_cast<Dog*>(&cat); // reinterpret_cast는 가능하다.
    p_dog->sound();

    return 0;
}

실행 결과

 

위 예제는 static_cast가 불가능한 상황에 사용했던 예제에서 static_cast를 reinterpret_cast로 바꾸어준 것이다. 놀랍게도 강아지가 고양이 울음 소리를 내며 울고 있다. 

위 코드처럼 잘못 사용하는 경우에는 결과 값이 컴파일러에 따라 다를 수 있고 예상하지 못한 결과를 발생시킬 수 있으므로 low level 수준의 cast를 요구하지 않을 경우 다른 cast 연산자의 사용을 권한다.


참고자료

https://learn.microsoft.com/ko-kr/cpp/cpp/static-cast-operator?view=msvc-170

https://learn.microsoft.com/ko-kr/cpp/cpp/dynamic-cast-operator?view=msvc-170

https://learn.microsoft.com/ko-kr/cpp/cpp/const-cast-operator?view=msvc-170

https://learn.microsoft.com/ko-kr/cpp/cpp/reinterpret-cast-operator?view=msvc-170

 

reinterpret_cast 연산자

자세한 정보: reinterpret_cast 연산자

learn.microsoft.com

https://blockdmask.tistory.com/236

https://blockdmask.tistory.com/241

https://blockdmask.tistory.com/240

https://blockdmask.tistory.com/242

 

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

안녕하세요 BlockDMask 입니다.이번에는 C++ 의 네가지 타입 캐스트 연산자 중에 (static_cast, const_cast, reinterpret_cast, dynamic_cast) reinterpret_cast 에 대해 알아보겠습니다.>reinterpret_cast 에 관한 기본 특성rein

blockdmask.tistory.com

https://uncertainty-momo.tistory.com/72

 

[c++] reinterpret_cast

또! 새로운 캐스트가 나타났습니다. 도대체 컴퓨터 언어 문법(?)의 다양함은 말로 이룰 수가 없네요 오늘도 그저 정리 할 뿐..... 머리에 박고 갑시다!!!! reinterpret_cast란? reinterpret_cast(expression); type_

uncertainty-momo.tistory.com

https://hwan-shell.tistory.com/219

 

C++] reinterpret_cast에 대해서...

모든 언어에는 형변환이 있습니다. C++에선 다양한 형번환 객체들을 제공합니다. 1. static_cast = https://hwan-shell.tistory.com/211 2. dynamic_cast = https://hwan-shell.tistory.com/213 3. const_cast = https://hwan-shell.tistory.c

hwan-shell.tistory.com

 

'언어' 카테고리의 다른 글

std::chrono의 간단한 사용  (4) 2024.10.30
STL  (1) 2023.10.29
Template  (0) 2023.10.29
스마트 포인터  (0) 2023.09.20
가상 함수  (0) 2023.09.04