"C++" C++ 유형 변환

"서문" 기사는 C++ 특수 유형 변환에 관한 것입니다.

"소속 칼럼" C Quack

"작가" Mr. Maple Leaf (fy)

"좌우명" 앞으로 가는 길에 나를 가꾸다

"메이플 리프 씨는 약간 지적 장애가 있습니다"

"기사당 한 문장"

어떤 것들은 희망을 보면 지속되지 않지만,
지속하기 때문에 희망이 보입니다.
——"열 가지 대죄"

목차

1. C언어에서 타입변환

2. C++에 네 가지 유형의 변환이 필요한 이유

3. C++ 필수 유형 변환

3.1 static_cast

3.2 reinterpret_cast

3.3 const_cast

3.4 dynamic_cast

4. RTTI


1. C언어에서 타입변환

C언어에서 대입 연산자의 좌변과 우변의 타입이 다르거나, 형식 참여자와 실제 매개변수의 타입이 일치하지 않거나, 반환값의 타입과 수신한 반환값의 타입이 일치하지 않는 경우 , 유형 변환이 발생해야 합니다.C 언어 유형 변환에는 암시적 유형 변환과 명시적 유형 변환의 두 가지 형식이 있습니다 .

  • 암시적 유형 변환: 컴파일러는 컴파일 단계에서 자동으로 변환을 수행합니다. 변환할 수 있으면 변환하고 변환할 수 없으면 컴파일에 실패합니다.
  • 명시적 유형 변환: 사용자가 처리해야 함
void Test()
{
	int i = 1;
	// 隐式类型转换
	double d = i;
	printf("%d, %.2f\n", i, d);

	int* p = &i;
	// 显示的强制类型转换
	int address = (int)p;
	printf("%x, %d\n", p, address);
}

단점: 전환의 시인성이 상대적으로 좋지 않고, 모든 전환 양식이 같은 형식으로 작성되어 있으며, 잘못된 전환 추적이 어렵다.

2. C++에 네 가지 유형의 변환이 필요한 이유

C 언어 스타일의 변환 형식은 매우 간단하지만 다음과 같은 많은 단점이 있습니다.

  1. 암시적 유형 변환은 경우에 따라 데이터 정밀도 손실과 같은 문제를 일으킬 수 있습니다.
  2. 명시적 유형 변환은 모든 사례를 함께 혼합하고 코드가 명확하지 않음

따라서 C++에서는 고유한 타입 변환 스타일을 제안하는데, C++은 C 언어와 호환되기 때문에 C++에서도 C 언어 변환 스타일을 사용할 수 있습니다.

3. C++ 필수 유형 변환

형식 변환의 가시성을 향상시키기 위해 표준 C++에서는 static_cast, reinterpret_cast, const_cast, dynamic_cast 라는 네 가지 명명된 캐스트 연산자를 도입했습니다.

3.1 static_cast

static_cast는 비다형적 유형의 변환(정적 변환)에 사용되며, 컴파일러에서 암시적으로 수행되는 모든 유형 변환은 static_cast를 사용할 수 있지만 관련 없는 두 유형의 변환에는 사용할 수 없습니다.

int main()
{
	double d = 12.34;
	int a = static_cast<int>(d);
	cout << a << endl;

	int* p = &a;
	// static_cast不能用于两个不相关类型之间转换
	//int address = static_cast<int>(p); //error
	return 0;
}

3.2 reinterpret_cast

reinterpret_cast 연산자는 일반적으로 한 유형을 다른 유형으로 변환하는 데 사용되는 피연산자의 비트 패턴에 대한 하위 수준 재해석을 제공합니다.

int main()
{
	int a = 10;
	int* p = &a;
	int address = reinterpret_cast<int>(p);
	cout << address << endl;
	return 0;
}

3.3 const_cast

const_cast의 가장 일반적인 용도는 할당을 용이하게 하기 위해 변수의 const 속성을 삭제하는 것입니다.

int main()
{
	const int a = 2;
	int* p = const_cast<int*>(&a);
	*p = 3;
	cout << a << endl;  
	cout << *p << endl; 
	return 0;
}

연산 결과

디버그 보기

설명하다:

  • 컴파일러는 const 수정된 변수가 수정되지 않을 것이라고 생각하기 때문에 const 수정된 변수를 레지스터에 저장하고 const 변수를 읽어야 할 때 레지스터에서 직접 읽어오며 우리가 수정하는 것은 실제로는 메모리에 있는 a의 값이므로 a의 최종 인쇄 값은 수정 전의 값입니다.
  • 컴파일러가 const 변수를 레지스터에 최적화하는 것을 원하지 않으면 volatile 키워드를 사용하여 const 변수를 수정할 수 있습니다. 이때 const 변수를 읽으려면 컴파일러가 메모리에서 읽습니다. 즉, Visibility 변수를 메모리에 유지합니다.

키워드 휘발성 추가

3.4 dynamic_cast

dynamic_cast는 상위 클래스 객체의 포인터/참조를 하위 클래스 객체의 포인터 또는 참조로 변환하는 데 사용됩니다(동적 변환).

  • 상향 변환: 하위 클래스 객체 포인터/참조 -> 상위 클래스 포인터/참조(변환 필요 없음, 할당 호환성 규칙)
  • 하향 변환: 상위 클래스 객체 포인터/참조 -> 하위 클래스 포인터/참조(dynamic_cast 변환을 사용하는 것이 안전함)

업캐스팅은 소위 자르기/슬라이싱으로 문법에서 자연스럽게 지원되며 변환이 필요하지 않으며, 다운캐스팅은 문법에서 지원되지 않으며 강제 유형 변환이 필요합니다.

알아채다:

  • dynamic_cast는 부모 클래스에 가상 함수가 포함된 클래스에만 사용할 수 있습니다.
  • dynamic_cast는 먼저 변환 성공 여부를 확인하고 성공하면 변환되고 그렇지 않으면 0을 반환합니다.

부모 클래스의 포인터(또는 참조)가 부모 클래스 객체를 가리키는 경우 이를 하위 클래스의 포인터(또는 참조)로 변환하는 것은 안전하지 않습니다. 부모 클래스 객체에 없는 것

class A
{
public:
	virtual void f() {}
};
class B : public A
{};
void fun(A* pa)
{
	// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回
	B* pb1 = (B*)pa;               //不安全
	B* pb2 = dynamic_cast<B*>(pa); //安全
	cout << "pb1:" << pb1 << endl;
	cout << "pb2:" << pb2 << endl;
}
int main()
{
	A a;
	B b;
	fun(&a);
	fun(&b);
	return 0;
}

컴파일 및 실행

dynamic_cast, 먼저 유형 검사를 수행하고 pa를 유형 B의 포인터 pb2로 안전하게 변환할 수 있으면 변환을 수행하고 그렇지 않으면 널 포인터를 리턴합니다. 이 방법은 프로그램 충돌이나 정의되지 않은 동작을 방지하는 데 더 안전합니다.

알아채다

  • 강제는 일반적인 유형 검사를 끄거나 중단합니다.강제를 사용하기 전에 프로그래머는 동일한 목표를 달성하기 위한 다른 방법이 있는지 신중하게 고려해야 합니다.비강압이 가능하지 않은 경우 강제 값을 제한해야 합니다. 오류 가능성.

강력한 권장 사항: 캐스트 사용을 피하십시오. 

4. RTTI

RTTI: 런타임 유형 식별의 약자, 즉 런타임 유형 식별

C++는 다음과 같은 방식으로 RTTI를 지원합니다.

  1. typeid 연산자
  2. dynamic_cast 연산자
  3. decltype

일반적인 면접 질문

C++의 4가지 유형의 변환은 다음과 같습니다.

  •  static_cast, reinterpret_cast, const_cast 및 dynamic_cast

4 유형 변환의 응용 시나리오 

  1. static_cast는 유형이 유사한 유형 간의 변환에 사용되며 컴파일러에서 암시적으로 수행되는 모든 유형 변환은 static_cast일 수 있습니다.
  2. reinterpret_cast는 관련 없는 두 유형 간의 변환에 사용됩니다.
  3. const_cast는 할당에 편리한 변수의 const 속성을 삭제하는 데 사용됩니다.
  4. dynamic_cast는 상위 클래스의 포인터(또는 참조)를 하위 클래스의 포인터(또는 참조)로 안전하게 변환하는 데 사용됩니다.

--------------------- 끝 ----------------------

「 作者 」 枫叶先生
「 更新 」 2023.5.15
「 声明 」 余之才疏学浅,故所撰文疏漏难免,
          或有谬误或不准确之处,敬请读者批评指正。

추천

출처blog.csdn.net/m0_64280701/article/details/130673014