C++ 중급 - Conversion

타입·2024년 1월 12일
0

C++ 공부

목록 보기
3/17
  • 변환 연산자
    객체가 다른 타입으로 변환될 때 호출되는 함수
    함수 이름에 이미 반환 타입이 포함되어 있으므로 반환 타입 미표기
operator TYPE()
{
	return 값;
}
  • 변환 생성자
class Int32
{
	int value;
public:
	Int32() : value(0) {}
	Int32(int n) : value(n) {} // 변환 생성자

	operator int() const { return value; } // 상수 멤버 함수로 만들면 활용도 증가
};

int main()
{
	int   pn; // Primitive Type
	Int32 un; // User Type

	pn = un; // un.operator int() 호출
	un = pn; // pn.operator Int32()는 int에 만들수 없어 아래 함수 찾음
	// 1. un.operator=(pn) 대입 연산자
	// 2. Int32(pn) 변환 생성자
}
  • Copy Initialization
class Int32
{
	...
	Int32(const Int32&) = delete; // 복사 생성자 삭제
}

int main()
{
	Int32 n = 3; // Int32 n = Int32(3);
}

C++14까진 임시객체를 생성하여 복사 생성자나 move 생성자 호출
C++17부턴 임시객체를 생성하지 않고 인자가 한 개인 생성자 호출

  • Conversion
class Int32
{
	...
	Int32& operator=(const Int32&) = delete; // 디폴트 대입 연산자 삭제
}
int main()
{
	n = 3; // n = Int32(3); 컴파일 에러
}

컴파일러에서 최적화를 통해서 임시객체 생성이 제거되지만 문법적으론 디폴트 대입 연산자 필요


  • explicit 생성자
    생성자가 암시적 변환의 용도로 사용될 수 없게 함
    Direct Initialization만 가능하고 Copy Initialization도 사용할 수 없음
class Vector
{
public:
	explicit Vector(int size) {}
};

void foo(Vector v) {} // Vector v = 3

int main()
{
	Vector v1(3); // Direct Initialization
	Vector v2 = 3; // Copy Initialization, 컴파일 에러
	Vector v3{3}; // Direct Initialization C++11
	Vector v4 = {3}; // Copy Initialization C++11, 컴파일 에러

	v1 = 3; // 컴파일 에러

	foo(3); // 컴파일 에러
}
  • explicit 변환 연산자
    암시적 변환은 안되지만 명시적 변환과 if문에선 사용 가능
class Machine
{
	int  data  = 10;
	bool state = true;
public:
	explicit operator bool() { return state;}
};

int main()
{
	Machine m;

	bool b1 = m; // error
	bool b2 = static_cast<bool>(m); // ok

	m << 10;  // error 

	if ( m )
	{		
	}
}
  • explicit(bool)
    괄호 안의 값이 true인 경우에만 explicit 동작
// C++20
#include <type_traits>

template<class T> 
class Number
{
	T value;
public:
	explicit(!std::is_integral_v<T>) Number(T v) : value(v) {}
};

int main()
{
	Number n1 = 10; // ok
	Number n2 = 3.4; // error
}

  • Return Type Resolver
    좌변을 보고 우변의 반환 타입을 자동으로 결정
struct Alloc
{
	std::size_t size;

	Alloc(std::size_t sz) : size(sz) {}

	template<class T>
	operator T*() { return new T[size]; }
};

int main()
{
	int*    p1 = Alloc(10); // 임시객체.operator int*()
	double* p2 = Alloc(10); // 변환 연산자가 템플릿이니 double도 가능
	
	delete[] p1;
	delete[] p2;
}
profile
주니어 언리얼 프로그래머

0개의 댓글