Casts

среда, апр. 2, 2025 | 3 минуты чтения

Casts

2 семестр
Основы программирования.

Какие касты существуют 🤔

  • Implicit (неявное)
  • Explicit (явное)
    • const_cast
    • static_cast
    • dynamic_cast
    • reintepret_cast
    • C-style cast

implicit cast

int main (int, char**) {
	double a = -12. 3456789;
	std:: cout < d << std:: endl;
	float f = d;
	std:: cout < f < std:: endl;
	int i = d;
	std:: cout << i << std:: endl;
	uint32_t ui = d;
	std:: cout << ui << std:: endl;
	char ch = d;
	std:: cout << ch << std:: endl;
	return 0;
}

C-style cast

Синтаксис: (type)a

int main(int, char**) {
	int i = 1;
	std::cout << *(double*)&i << std::endl;
}

const_cast

  • убирает const или volatility с переменной

  • может преобразовывать указатели на одинаковые типы данных

  • может преобразовывать ссылки

  • const_cast используется только, если есть уверенность, что это будет не константа

  • const_cast ом нужно пользоваться очень аккуратно

static_cast

  • пытается выполнить преобразование с помощью конструкторов и операторов приведения

  • работает в момент compile-time (быстро работает)

  • работает для стандартных типов (замена c-style касту)

  • работает для приведения указателей из одной иерархии

  • может приводить из указателя на void*

  • гарантия на поиск цепочки преобразований. Если такой цепочки нет, то просто не скомпилируется

  • может кастовать из одной иерархии, но в примере объект уже был дерайвд, а потом стал указателем на бейз. После этого скаставалось

  • Даже если изначально было бейз, то при касте к дерайвд будет полноценным дерайвд

  • не всегда будет работать, если кастуем от базового к дерайвд, потому что есть новое поле, которое никак не конструируется новое поле

  • не позволяет проверить, является ли такое наследование из иерархии классов возможным

dynamic_cast

  • преобразует указатели и ссылки вниз и вверх по иерархии

  • RTTI (динамическая идентификация типа данных)

  • std::bad_cast

  • таблица виртуальных функций помогает проверить в ран-тайме, находится ли такой класс ниже по иерархии. Соответственно есть проверка кастом

    • либо нульптр(если указатель)
    • либо bad_cast exception (в других)
  • плата работай в ран-тайме

    • доп время процесса
    • обязаны иметь таблицу виртуальных функций(=> доп память), иначе классы неполиморфные и ошибка компиляции

reintepret_cast

страшно, бойтесь, противозаконно…

  • позволяет кастовать несовместимые типы (и ничего не думает)

  • использует исключительно побитовое представление

  • нужно быть чётко уверенным, что в нужном блоке памяти лежит то, с чем мы можем это делать

  • если чётко знаем, что это, то можем использовать

    • к примеру ясную структуру кастуем к чарикам(байтам) и выводим в файл, а потом читаем из него, чётко зная размер этой структуры кастуем обратно
    • проблема выравнивания
    • проблема разных размеров переменных на разных компьбтерах
    • числа могут в памяти храниться по-разному (биг-эндиан и литл-эндиан)
    • флоты могут храниться по-разному
  • Если делаем всегда на одном и том же комптютере, то можем быть спокойны

  • Можно ускорять всякие вещи для записи в файл с помощью reintepret_cast

    • можем взять бинарный файл и класть в него все чиселки (даже пара чиселок), кастуя указатель на начало вектора к указателю на чарики. Всего один системный вызов на райт => будет быстрее и меньше по памяти