"C++" Преобразование типа C++

Статья «Предисловие» посвящена преобразованию специальных типов C++.

"Принадлежащая колонка" C Quack

"Автор" Мистер Мэйпл Лиф (fy)

«Девиз» Совершенствовать себя на пути вперед

«Мистер Мэйпл Лиф немного умственно отсталый»

«Одно предложение в статье»

Некоторые вещи не сохраняются, когда вы видите надежду,
но вы видите надежду, потому что упорствуете.
—— «Десять смертных грехов»

Оглавление

1. Преобразование типов на языке C

2. Зачем C++ нужны четыре типа преобразований

3. Обязательное преобразование типов C++

3.1 статическая_каст

3.2 повторная интерпретация_cast

3.3 const_cast

3.4 динамическое_каст

4. РТТИ


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, но его нельзя использовать для преобразования двух несвязанных типов.

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 повторная интерпретация_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;
}

результат операции

представление отладки

объяснять:

  • Поскольку компилятор думает, что константно-модифицированные переменные не будут модифицированы, он будет хранить константно-модифицированные переменные в регистре, а когда ему нужно будет прочитать константную переменную, он будет читать ее прямо из регистра, а то, что мы модифицируем, фактически является значением a в памяти, поэтому окончательное напечатанное значение a является значением до модификации.
  • Если вы не хотите, чтобы компилятор оптимизировал константную переменную в регистр, вы можете использовать ключевое слово volatile для изменения константной переменной.В это время, когда вы хотите прочитать константную переменную, компилятор прочитает ее из памяти , то есть оставить переменную Visibility в памяти

Добавить ключевое слово volatile

3.4 динамическое_каст

dynamic_cast используется для преобразования указателя/ссылки объекта родительского класса в указатель или ссылку объекта подкласса (динамическое преобразование).

  • Восходящее преобразование: указатель/ссылка на объект подкласса -> указатель/ссылка на родительский класс (преобразование не требуется, правила совместимости присваивания)
  • Нисходящее преобразование: указатель/ссылка на объект родительского класса -> указатель/ссылка подкласса (безопасно использовать преобразование dynamic_cast)

Upcasting — это так называемая cut/slicing, которая естественным образом поддерживается грамматикой и не требует преобразования, а downcasting грамматикой не поддерживается и требует принудительного преобразования типов.

Уведомление:

  • 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 в указатель pb2 типа B, затем выполнит преобразование, иначе вернет нулевой указатель. Этот метод безопаснее, чтобы избежать сбоев программы или непредвиденного поведения.

Уведомление

  • Приведение отключает или приостанавливает обычную проверку типов.Перед каждым использованием приведения программист должен тщательно рассмотреть, существуют ли другие способы достижения той же цели.Если неприведение невозможно, значение приведения должно быть ограничено. вероятность ошибок.

Настоятельная рекомендация: избегайте использования приведения 

4. РТТИ

RTTI: сокращение от «Идентификация типа во время выполнения», а именно: идентификация типа во время выполнения.

C++ поддерживает RTTI следующими способами:

  1. оператор typeid
  2. оператор dynamic_cast
  3. decltype

общие вопросы интервью

4 типа преобразований в C++:

  •  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
「 声明 」 余之才疏学浅,故所撰文疏漏难免,
          或有谬误或不准确之处,敬请读者批评指正。

Supongo que te gusta

Origin blog.csdn.net/m0_64280701/article/details/130673014
Recomendado
Clasificación