- static_cast, dynamic_cast등 여러종류의 type cast들을 실습
- 문자열을 인자로받고 이 문자열을 char, int, float, double로 변환하여 출력
- 출력할 수 없는 char은 표시할 수 없다고 출력
- 결과를 도출할 수 없거나 오버플로우가 발생시 impossible 출력
- +inf, -inf, +inff, -inff, nan, nanf를 입력시 맞게 출력
./convert 0 char: Non displayable int: 0 float: 0.0f double: 0.0 ./convert nan char: impossible int: impossible float: nanf double: nan ./convert 42.0f char: '*' int: 42 float: 42.0f double: 42.0
static_cast
static_cast<바꾸려고 하는 타입>(대상);
- 형변환시 사용되며 잘못된 형 변환에대한 오류를 체크해줌
- double -> char 같은 사이즈가 작아지는 상황에서는 값이 사라질 수 있음
- 일반 포인터의 변환은 안되지만 상속관계의 포인터끼리 변환 가능, 다만 다운캐스트시 안전하지않음
Convert 클래스
class Convertor { private: std::string _input; int _type; int _int; float _float; double _double; char _char; void startConvert(); void checkInput(); float toFloat(); char toChar(); double toDouble(); int toInt(); Convertor(); public: Convertor(const std::string input); Convertor(const Convertor &c); Convertor &operator=(const Convertor &c); std::string getInput() const; float getFloat() const; char getChar() const; double getDouble() const; int getInt() const; int getType() const; void printConvert(); ~Convertor(); class excep: public std::exception { public: const char* what( void ) const throw(); }; };
- 구조가 있는 객체의 내용물을 바이트 배열로 저장하는 것을 Serialization이라고 하고 바이트 배열로부터 읽어온 뒤 구조가 있는 객체에 채우는 것을 Deserialization라고 함
- Data구조체를 uintptr_t형으로 변환한 뒤 다시 Data형으로 변환하고 주소와 데이터가 잘 남아있는지 확인
reinterpret_cast
reinterpret_cast<바꾸려고 하는 타입>(대상);
- 임의의 포인터간 변환시 사용하는 cast
- 포인터 -> 포인터, 포인터 -> 일반변수, 일반변수 -> 포인터
- int* -> char처럼 크기가 작아지면 데이터 손실이 일어남
uintptr_t serialize(Data* ptr) { return(reinterpret_cast<uintptr_t>(ptr)); } Data* deserialize(uintptr_t raw) { return(reinterpret_cast<Data *>(raw)); }
- 가상 소멸자만 소유하는 Base클래스와 이를 상속받는 A, B, C 클래스를 생성
- A, B, C 클래스를 무작위로 생성하여 반환하는 Base * generate(void);
- 포인터로 A, B, C클래스를 인자로 받아 해당하는 클래스가 어떤 클래스인지 출력하는 void identify(Base* p);
- 참조로 A, B, C클래스를 인자로 받아 해당하는 클래스가 어떤 클래스인지 출력하는 void identify(Base& p);
- <typeinfo>는 사용금지
dynamic_cast
dynamic_cast<바꾸려고 하는 타입>(대상);
- dynamic_cast는 상속관계에 있는 객체의 포인터나 참조형 타입을 변환할 때 사용함
- 포인터타입의 dynamic_cast는 타입이 맞지않을경우 NULL을 반환함
- 참조타입의 dynamic_cast는 타입이 맞지않을경우 bad casting exception을 throw함
void identify(Base* p) // 포인터타입의 dynamic_cast는 타입이 맞지않을경우 NULL을 반환함 { if (dynamic_cast<A *>(p) != NULL) std::cout << "pointed actual type = A" << std::endl; else if (dynamic_cast<B *>(p) != NULL) std::cout << "pointed actual type = B" << std::endl; else if (dynamic_cast<C *>(p) != NULL) std::cout << "pointed actual type = C" << std::endl; else std::cout << "unknown type" << std::endl; } void identify(Base& p) // 참조타입의 dynamic_cast는 타입이 맞지않을경우 bad casting exception을 throw함 { try { A &a = dynamic_cast<A &>(p); std::cout << "ref actual type = A" << std::endl; (void) a; return ; } catch(const std::exception& e) { } try { B &b = dynamic_cast<B &>(p); (void) b; std::cout << "ref actual type = B" << std::endl; return ; } catch(const std::exception& e) { } try { C &c = dynamic_cast<C &>(p); (void) c; std::cout << "ref actual type = C" << std::endl; return ; } catch(const std::exception& e) { } }