C++프로그래밍/C++ 객체지향

타입 변환의 여러 관점

season97 2024. 9. 22. 12:53
728x90
반응형

※ C / C++을 이미 알고 있으나 개인적인 복습 및 공부를 위해 포스팅 하는 글이므로

C++에 대한 구체적인 정보를 담고 있지 않습니다.


 

 ▶ 타입 변환의 여러가지 관점에 따른 분류

 

ㆍ 비트열 재구성 여부, 안전도에 따른 분류, 프로그래머 의도에 따른 분류, 클래스간의 변환..


 

----------타입 변환의 유형 (비트열 재구성 여부)----------

 

 1) 값 타입 변환

 ㆍ 의미를 유지하기 위해서, 원본 객체와 다른 비트열 재구성.. 뭔소리냐?

int a = 123456789; //2의 보수
float b = float(a);//부동소수점(지수+유효숫자)
cout << b << endl;
//메모리를 찍어보면 a엔 16진수로 123456789가 저장돼있고
//b엔 16진수로 의미가 비슷한 근접한 숫자가 저장되어있다

ㆍ 즉 의미를 유지하기 위해 최~대한 근접하게 해줌

 

2) 참조 타입 변환

ㆍ 비트열을 재구성 하지 않고, "관점"만 바꾸는 것

int a = 123456789; //2의 보수
float b = (float&)a;//부동소수점(지수+유효숫자)
cout << b << endl;

 

---------- 안전도 분류 ----------

 

1) 안전한 변환

ㆍ 의미가 항상 100% 일치하는 경우

ㆍ 같은 타입이면서 크기만 더 큰 바구니로 이동하는 경우

ㆍ 작은 바구니 -> 큰 바구니로 이동 ok (이걸 업케스팅 이라고 한다)
ex) char -> short, short -> int

int a = 123456789;
__int64 b = a;
cout << b << endl; //문제없이 실행

 

 

2) 불안전한 변환 


ㆍ 의미가 항상 100% 일치한다고 보장하지 못하는 경우....


→ 타입이 다르거나, 같은 타입이지만 큰 바구니 -> 작은 바구니인 경우 (다운캐스팅)

int a = 123456789;
float b = a; // 1.2345..... 뭐 근사값 맞출라고 노력
short c = a; // 프로그래머 계산기 기준 short만큼만(2바이트) 분석하고 나머지 버림...

 

 

 

 

----------프로그래머 의도에 따른 분류----------

 1) 암시적 변환

 ㆍ 이미 알려진 타입 변환 규칙에 따라 컴파일러가 "자동"으로 타입 변환

int a = 123456789;
float b = a; // 암시적으로 알아서 해주는 상황

 

2) 명시적 변환

 int a = 123456789;
 int* b = (int*)a; // 이건 암시적으로 안댐...명시해줘

위험한거 알고... 자동으로 해주는거 싫은거 알겠는데.. 그래도 해줘!

 

 

 

----------아무런 연관 관계가 없는 클래스 사이의 변환----------

 

 1) 연관 없는 클래스 사이의 "값 타입" 변환
 

ㆍ 일반적으로 안됨 (타입변환 생성자를 만들어서 예외적으로 해야댐)

class Knight
{
public:
    int _hp = 10;
};

class Dog
{
public:
    int _age = 1;
    int _cuteness = 2;
};
 Knight knight;
 Dog dog = (Dog)knight; 
 //기사랑 개사이엔 아무관계가 없어서 명시든,암시든 안됨 (타입변환 생성자 생성하면됨)
 Knight knight2 = dog;

ㆍ 두 코드 다 안되는게 정상인데 어거지로 되게 할 수 있는 방법이 있긴 하다..

class Dog
{
public:
    //타입 변환 생성자
    Dog(const Knight& knight)
    {
        _age = knight._hp;
    }

    //타입 변환 연산자
    operator Knight()
    {
        return (Knight)(*this);
    }
    int _age = 1;
    int _cuteness = 2;
};

ㆍ 이렇게 해주면 위 코드들의 오류가 사라지긴 한다

 

 

 2) 연관 없는 클래스 사이의 "참조 타입" 변환

 ㆍ 위 타입 변환 연산자와 타입변환 생성자는 값 타입에서만 적용이 된다...        

        Knight knight;
        //Dog& dog = knight;    //안댐...
        // 
        // 어셈블리 : 포인터 = 참조
        // C++에선 다르지만 어셈블리에선 같았다 
        // 
        // [ 주소 ]  ->  [ Dog ] 
        Dog& dog = (Dog&)knight; //이건또 됨;; 진짜인지 아닌지를 컴파일타임에서 체크하지 않는것이다...
        // 어셈블리 입장에선 주소라 함은 꼭 dog를 가리키지 않아도 상관이 없기때문에(null이여도 괜찮) 그래서 일단
        // 컴파일타임 에서는 오류를 잡아주지 않는 것이다 (명시적으로는 ok)
        // 

        dog._cuteness = 12; //이런식으로 가리키면 터질껄~

ㆍ 포인터 관련 사용 문제를 조심히자, 댕글링포인터 주의

 


    

----------상속 관계 클래스 사이의 변환----------

 

 

1) 상속 관계 클래스의 값 타입 변환
 ㆍ 자식-> 부모 OK / 부모 -> 자식 NO

 // Dog dog;
//  BullDog bulldog = (BullDog)dog; 안댐!
BullDog bulldog;
Dog dog = bulldog;

 

 

2) 상속 관계 클래스의 참조 타입 변환
ㆍ 자식-> 부모 OK / 부모 -> 자식 NO

ㆍ 허용은 하지만... 쫌 그럼... 포인터 관련 문제 주의

Dog dog;
BullDog& bulldog =(BullDog&)dog; //되긴 함

BullDog bulldog;
Dog& dog = bulldog;

 

728x90
반응형