결론)
[값 타입 변환] : 진짜 비트열도 바꾸고 - 논리적으로 말이 되게 바꾸는 변환 // 내부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;
}
'C++,python (인프런+사이트) > C++ 동적 할당' 카테고리의 다른 글
동적할당_3_(new[]/delete[]) (0) | 2022.02.07 |
---|---|
동적할당_1_2_(malloc_free) (0) | 2022.02.02 |
댓글