본문 바로가기
C++,python (인프런+사이트)/C++ 동적 할당

타입변환_1_2

by 알 수 없는 사용자 2022. 3. 8.

결론)
[값 타입 변환] : 진짜 비트열도 바꾸고 - 논리적으로 말이 되게 바꾸는 변환  // 내부data가 변경되는 경우
- 논리적으로 말이 된다? (ex . Dog = BullDog ) OK
- 논리적으로 말이 안된다 (ex . BullDog = Dog , Knight = Dog ) 안됨
[참조 타입 변환 ] : 비트열은 냅두고 우리의 '관점'만 바꾸는 변환  // *포인터, &참조   주소메모리관련해서
- 땡깡 부리면(명시적 요구) 해주긴 하는데, 말 안해도 '그냥'(암시적)으로 해주는 지는 안전성 여부를 검사한다.
-- 안전하다 ? (ex. &Dog = BullDog ) '그냥'(암시적으로)OK
-- 위험하다 ? (ex. &BullDog = Dog ) 메모리 침범 위험이 있는 경우는 '그냥'(암시적으로) 해주진 않음
--- 명시적으로 하겠다 라고 최종 서명(변환)을 하면 OK

 

 

코드

더보기
#include<iostream>
using namespace std;

// 오늘의 주제 : 캐스팅 (타입 변환)

// malloc -> void*을 반환하고, 이를 우리가 (타입 변환)을 통해 사용했었음

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

class Dog {
public:
	Dog() {}

	// 타입 변환 생성자 //Knight를 Dog형으로 형변환 시킬 수 있다! 라는 정의가 필요하다.
	Dog(const Knight& knight)
	{
		_age = knight._hp;
	}

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

class BullDog : public Dog // 강아지 >> 불독 // 상속관계가 있다.(사람판단에)
{
public:
	bool _french; // 프렌치불독
};


int main() {
	// ------------- 타입 변환 유형 -------------

	// [1] 값 타입 변환
	// int -> float 으로 같은것들

	// [2] 참조 타입 변환
	// 포인터 타입 변환도 '참조 타입 변환'과 동일한 룰임.
	{
		int a = 123456789;
		float b = (float&)a;
		cout << b << endl;
	}


	// ------------- 안전도 분류 ----------------
	// [1] 안전한 변환
	// 특징) 의미가 항상 100% 일치하는 경우
	// 같은 타입이면서 크기가 더 큰 바구니로 이동하는 경우
	// 작은 바구니 --> 큰 바구니로 이동 OK (업캐스팅)
	{
		int a = 123456789;
		__int64 b = a;
		cout << b << endl;
	}

	// [2] 불안전환 변환
	// 특징) 의미가 항상 100% 일치한다고 보장하지 못하는 경우
	// 타입이 다르거나
	// 같은 타입이지만 "큰 바구니 --> 작은 바구니" 이동 (다운캐스팅)
	{
		int a = 123456789;
		float b = a;
		short c = a;
		cout << b << endl;
		cout << c << endl;
	}
	

	// ------------- 프로그래머 의도에 따라 분류 ----------------
	// [1] 암시적 변환
	// 특징) 이미 알려진 타입 변환 규칙에 따라서 컴파일러 ' 자동'으로 타입 변환
	{
		int a = 123456789;
		float b = a; //암시적
		cout << b << endl;
	}

	// [2] 명시적 변환
	{
		int a = 123456789; // int형 포인터 b 에 <-- a변수를 int형 포인터로 형변환해서 대입
		int* b = (int*)a;  // 명시적
		cout << b << endl;
	} 


	// ------------- 아무런 연관 관계가 없는 클래스 사이의 변환 ---------
	// [1] 연관없는 클래스 사이의 "값 타입" 변환
	// 특징) 일반적으로 안 됨 ( '타입 변환 생성자',or '타입 변환 연산자' 필요)
	{
		Knight k;

		//타입 변환 생성자
		Dog d = (Dog)k;
		//타입 변환 연산자
		Knight k2 = d;
	} //결론 : 엄격한 이유는 -> 직접적인 data -> data 이기 때문에 문법상 NO!

	// [2] 연관없는 클래스 사이의 참조 타입 변환
	{
		Knight k;
		//Dog d = k;
		// 어셈블리 상에선 -> : 포인터 == 참조 이다.

		// [ 주소 ] -> [ Dog ] 형태
		Dog& d2 = (Dog&)k; // 사기치는거라고 할 수 있다.
		// Dog가 있는 참조주소값으로 형변환 했으니 빌드가 되는 것
		d2._cuteness = 12; // knight는 size가 4byte낮다. -> 이상한 메모리 건들게 됨.
	} //결론 : 느슨한 이유는 -> 간접적인 주소 -> 주소 이기 때문에 문법상 OK!


	// ------------- 상속 관계에 있는 클래스 사이의 변환 ----------
	// 특징) 자식 -> 부모 OK / 부모 -> 자식 NO
	// [1] 상속 관계 클래스의 값 타입 변환
	{
		//Dog dog; // Dog는 _age _cuteness 를 가진 상태
		//BullDog bulldog = (BullDog)dog;

		BullDog bulldog2; // BullDog은 _age _cuteness _french 전부 가진상태
		Dog dog2 = bulldog2; // 따라서 Dog에는 _french가 없으니까 "_age _cuteness" 정보만 들어간 형태로 만들어진다. 
	} //Dog 는 4byte  ,   bulldog 은 8byte

	// [2] 상속 관계 클래스의 참조 타입 변환 
	// 특징) 자식->부모 OK / 부모->자식 (암시적NO)(명시적OK)
	{ //느슨함 주소->주소 어거지로 집어넣는거
		//Dog dog;
		//BullDog& bulldog = (BullDog&)dog;

		// [age cuteness french]
		BullDog bulldog;
		Dog& dog = bulldog;
	}
/*
결론)
[값 타입 변환] : 진짜 비트열도 바꾸고 - 논리적으로 말이 되게 바꾸는 변환
- 논리적으로 말이 된다? (ex . Dog = BullDog ) OK
- 논리적으로 말이 안된다 (ex . BullDog = Dog , Knight = Dog ) 안됨
[참조 타입 변환 ] : 비트열은 냅두고 우리의 '관점'만 바꾸는 변환
- 땡깡 부리면(명시적 요구) 해주긴 하는데, 말 안해도 '그냥'(암시적)으로 해주는 지는 안전성 여부를 검사한다.
-- 안전하다 ? (ex. &Dog = BullDog ) '그냥'(암시적으로)OK
-- 위험하다 ? (ex. &BullDog = Dog ) 메모리 침범 위험이 있는 경우는 '그냥'(암시적으로) 해주진 않음
--- 명시적으로 하겠다 라고 최종 서명(변환)을 하면 OK
*/



	return 0;
}

댓글