Различия
Показаны различия между двумя версиями страницы.
— | preobrazovanie_tipov [2021/07/31 21:58] (текущий) – создано - внешнее изменение 127.0.0.1 | ||
---|---|---|---|
Строка 1: | Строка 1: | ||
+ | ====== Преобразование типов в стиле С ====== | ||
+ | {{htmlmetatags> | ||
+ | metatag-description=(Синтаксис: | ||
+ | }} | ||
+ | |||
+ | Когда, мы что-либо делаем, | ||
+ | |||
+ | Итак, прежде всего, давайте разберемся с тем, как типы данных взаимодействуют друг с другом. Существует так называемая иерархия типов, где все типы размещены по старшинству. Для того, что бы разбираться в преобразовании типов, необходимо всегда помнить порядок типов этой иерархии. | ||
+ | < | ||
+ | bool, | ||
+ | </ | ||
+ | Несмотря на то, что некоторые типы имеют одинаковый размер, | ||
+ | |||
+ | Теперь, | ||
+ | |||
+ | Классификация по диапазону содержащихся значений. | ||
+ | Все преобразования можно разделить на две группы относительно местоположения в иерархии типов участвующих в преобразовании. | ||
+ | |||
+ | * **Сужающее преобразование** – при таком преобразовании - больший тип данных в иерархии преобразуется к меньшему типу, безусловно, | ||
+ | < | ||
+ | int A=23.5; | ||
+ | cout<< | ||
+ | </ | ||
+ | |||
+ | * **Расширяющее преобразование**. Данный вид преобразования, | ||
+ | < | ||
+ | unsigned int a=3000000000; | ||
+ | cout<< | ||
+ | </ | ||
+ | В данном случае 3000000000 - это литерал типа int, который благопоучно расширяется до unsigned int, что и позволяет нам увидеть на экране именно 3000000000, а не что-то другое. Тогда, как в обычный int такое число не поместиться. | ||
+ | |||
+ | ====== Классификация по способу осуществления преобразования ====== | ||
+ | Вне зависимости от направления преобразования, | ||
+ | |||
+ | - **Неявное преобразование**. Все вышеописанные примеры относились к этому типу преобразования. Такой вид преобразования также называют автоматическим, | ||
+ | float A=23,5; - double стал | ||
+ | </ | ||
+ | - **Явное преобразование**. (второе название – приведение типов). В данном случае, | ||
+ | double z=37.4; | ||
+ | float y=(int) z; | ||
+ | cout<< | ||
+ | </ | ||
+ | (int)z – есть явное сужающее преобразование от типа double к типу int. В этой же строке происходит расширяющее неявное преобразование от полученного типа int к типу float. Следует запомнить, | ||
+ | |||
+ | ====== Преобразование типов в выражении ====== | ||
+ | И, вот, мы наконец-то подошли к тому, о чем говорили в самом начале данного раздела урока, как выяснить какого типа будет результат какого-то выражения. Давайте попробуем это вычислить, | ||
+ | int I=27; | ||
+ | short S=2; | ||
+ | float F=22.3; | ||
+ | bool B=false; | ||
+ | </ | ||
+ | Пользуясь этими переменными, | ||
+ | I-F+S*B | ||
+ | </ | ||
+ | В переменную какого типа данных нам следует записать результат? | ||
+ | int-float+short*bool | ||
+ | </ | ||
+ | Напоминаем, | ||
+ | < | ||
+ | int-float+int*int, | ||
+ | </ | ||
+ | Умножение int на int даст, несомненно, | ||
+ | **Если в каком-либо выражении используются разные типы данных, | ||
+ | Ну и, наконец – вычитание из int типа float, согласно только что упомянутому правилу снова даст float. | ||
+ | Таким образом, | ||
+ | < | ||
+ | float res= I-F+S*B; // 27-22.3+2*0 | ||
+ | cout<< | ||
+ | </ | ||
+ | Теперь, | ||
+ | |||
+ | **Примечание: | ||
+ | |||
+ | ===== Пример, | ||
+ | Теперь давайте закрепим знания на практике. Создадим проект и напишем нижеследующий код. | ||
+ | < | ||
+ | # include < | ||
+ | using namespace std; | ||
+ | void main(){ | ||
+ | |||
+ | // объявление переменных и запрос на ввод данных | ||
+ | float digit; | ||
+ | cout<<" | ||
+ | cin>> | ||
+ | |||
+ | /* Даже, если пользователь ввел число с вещественной частью, | ||
+ | результат выражения запишется в int и вещественная часть будет утеряна, | ||
+ | разделив число на 100 мы получим количество сотен в нем. */ | ||
+ | int res=digit/ | ||
+ | cout<< | ||
+ | } | ||
+ | </ | ||
+ | Теперь, | ||
+ | ====== Преобразование типов в стиле С++ ====== | ||
+ | Для начала напомним, | ||
+ | < | ||
+ | (тип) выражение | ||
+ | |||
+ | Например, | ||
+ | |||
+ | double d; | ||
+ | d=(double) 10/3; | ||
+ | </ | ||
+ | ===== Операторы приведения типа в языке С++ ===== | ||
+ | Кроме стандартной формы в стиле С, язык С++ поддерживает дополнительные операторы приведения типа. Вполне очевидны положительные стороны этих новых способов. Во-первых данные преобразования позволяют сделать то, чего стандарт языка С даже не предполагал: | ||
+ | * const_cast< | ||
+ | * dynamic_cast< | ||
+ | * reinterpret_cast< | ||
+ | * static_cast< | ||
+ | |||
+ | const_cast используется для явного переопределения модификаторов const и/или volatile. Новый тип должен совпадать с исходным типом, за исключением изменения его атрибутов const или volatile. Чаще всего оператор const_cast используется для снятия атрибута const. Например: | ||
+ | |||
+ | < | ||
+ | < | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | // указатель на объект является константным, | ||
+ | // следовательно, | ||
+ | // объекта нельзя | ||
+ | void test_pow(const int* v){ | ||
+ | int*temp; | ||
+ | // снимаем модификатор const | ||
+ | // и теперь можем изменять объект | ||
+ | temp=const_cast< | ||
+ | // изменение объекта | ||
+ | *temp= *v * *v; | ||
+ | } | ||
+ | void main(){ | ||
+ | int x=10; | ||
+ | // на экране - 10 | ||
+ | cout<<" | ||
+ | test_pow(& | ||
+ | // на экране - 100 | ||
+ | cout<<" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Примечание: | ||
+ | |||
+ | **dynamic_cast** проверяет законность выполнения заданной операции приведения типа. Если такую операцию выполнить нельзя, | ||
+ | |||
+ | < | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | // базовый класс | ||
+ | class B{ | ||
+ | public: | ||
+ | // виртуальная функция для | ||
+ | // последующего переопределения в потомке | ||
+ | virtual void Test(){ | ||
+ | cout<<" | ||
+ | } | ||
+ | }; | ||
+ | // класс-потомок | ||
+ | class D:public B{ | ||
+ | public: | ||
+ | // переопределение виртуальной функции | ||
+ | void Test(){ | ||
+ | cout<<" | ||
+ | } | ||
+ | }; | ||
+ | void main(){ | ||
+ | // указатель на класс-родитель | ||
+ | // и объект класса-родителя | ||
+ | B *ptr_b, obj_b; | ||
+ | // указатель на класс-потомок | ||
+ | // и объект класса-потомка | ||
+ | D *ptr_d, obj_d; | ||
+ | |||
+ | // приводим адрес объекта (D*) к указателю типа D* | ||
+ | ptr_d= dynamic_cast< | ||
+ | // если все прошло успешно - вернулся !0 | ||
+ | // произошло приведение | ||
+ | if(ptr_d){ | ||
+ | cout<<" | ||
+ | // здесь вызов функции класса-потомка | ||
+ | // на экране - Test D | ||
+ | ptr_d-> | ||
+ | } | ||
+ | // если произошла ошибка - вернулся 0 | ||
+ | else cout<<" | ||
+ | |||
+ | // приводим адрес объекта (D*) к указателю типа B* | ||
+ | ptr_b= dynamic_cast< | ||
+ | // если все прошло успешно - вернулся !0 | ||
+ | // произошло приведение | ||
+ | if(ptr_b){ | ||
+ | cout<<" | ||
+ | // здесь вызов функции класса-потомка | ||
+ | // на экране - Test D | ||
+ | ptr_b-> | ||
+ | } | ||
+ | // если произошла ошибка - вернулся 0 | ||
+ | else cout<<" | ||
+ | |||
+ | // приводим адрес объекта (B*) к указателю типа B* | ||
+ | ptr_b= dynamic_cast< | ||
+ | // если все прошло успешно - вернулся !0 | ||
+ | // произошло приведение | ||
+ | if(ptr_b){ | ||
+ | cout<<" | ||
+ | // здесь вызов функции класса-потомка | ||
+ | // на экране - Test B | ||
+ | ptr_b-> | ||
+ | } | ||
+ | // если произошла ошибка - вернулся 0 | ||
+ | else cout<<" | ||
+ | |||
+ | // ВНИМАНИЕ!!! ЭТО НЕВОЗМОЖНО | ||
+ | // попытка привести адрес объекта (B*) к указателю типа D* | ||
+ | ptr_d= dynamic_cast< | ||
+ | // если все прошло успешно - вернулся !0 | ||
+ | // произошло приведение | ||
+ | if(ptr_d) | ||
+ | cout<<" | ||
+ | // если произошла ошибка - вернулся 0 | ||
+ | else cout<<" | ||
+ | } | ||
+ | Результат работы программы: | ||
+ | Good work - Test D | ||
+ | Good work - Test D | ||
+ | Good work - Test B | ||
+ | Error work!!! | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | static_cast выполняет неполиморфное приведение типов. Его можно использовать для любого стандартного преобразования. При этом никакие проверки во время работы программы не выполняются. Фактически, | ||
+ | |||
+ | < | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | void main(){ | ||
+ | int i; | ||
+ | for(i=0; | ||
+ | // приведение переменной i к типу double | ||
+ | // результаты деления на экране, | ||
+ | // вещественные | ||
+ | cout<< | ||
+ | } | ||
+ | </ | ||
+ | reinterpret_cast переводит один тип в совершенно другой. Например, | ||
+ | |||
+ | < | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | void main(){ | ||
+ | // целочисленная переменная | ||
+ | int x; | ||
+ | // строка (указатель типа char) | ||
+ | char*str=" | ||
+ | // демонстрируем строку на экран | ||
+ | cout<< | ||
+ | // преобразуем указатель типа char в число | ||
+ | x=reinterpret_cast< | ||
+ | // демонстрируем результат | ||
+ | cout<< | ||
+ | } | ||
+ | </ | ||
+ | ===== RTTI ===== | ||
+ | * [[wpru> | ||
+ | В C++ для динамической идентификации типов применяются операторы dynamic_cast и typeid (определён в файле typeinfo.h), | ||
+ | * Оператор **dynamic_cast** пытается выполнить приведение к указанному типу с проверкой. Целевой тип операции должен быть типом указателя, | ||
+ | * Оператор **typeid** возвращает ссылку на структуру type_info, которая содержит поля, позволяющие получить информацию о типе. |
📌 Удобный подбор VPS по параметрам доступен на DIEGfinder.com - официальном инструменте проекта DIEG. Это часть единой экосистемы, созданной для того, чтобы помочь быстро найти подходящий VPS/VDS сервер для любых задач хостинга.
📌 Для тестирования скриптов, установщиков VPN и Python-ботов рекомендуем использовать надежные VPS на короткий срок. Подробнее о быстрой аренде VPS для экспериментов - читайте здесь.
💥 Подпишись в Телеграм 💥 и задай вопрос по сайтам и хостингам бесплатно!7 Самых Популярных Статей
- Как запустить скрипты и веб-приложения на Python
- Что такое страны TIER 1,2,3
- 7 способов сравнения файлов по содержимому в Windows или Linux
- Установка и тестирование веб-панели HestiaCP
- Nginx простые примеры конфигурации
- top, htop, atop определение загрузки ОС (Load average, LA)
- Использование rsync в примерах
7 Самых Популярных Обзоров
- Хостинг для Python-скриптов и приложений
- ТОП 4 лучших антидетект браузеров (Бесплатные & Платные)
- Подборка купонов (промокоды) на хостинг, антидетект браузеры
- Обзор THE.Hosting (PQ Hosting): надежный хостинг с профессиональной поддержкой
- Хостинг в России
- Хостинг в Европе
- Обзор браузера Dolphin {anty} для мультиаккаунтинга