Qbik-club
Дата публикации:31.10.21 17:41;Автор:Евгений;Категория: программирование;Теги:, ;

Явное и не явное преобразование типов в С++

Сегодня, в продолжении темы изучения языка программирования С++, я, как и обещал в прошлой публикации, расскажу о преобразовании типов. Расскажу, чем отличается явное и неявное преобразование, в каких случаях это может помочь, а в каких — стать серьёзной проблемой. И что об этом нужно знать.

Явное и не явное преобразование типов в С++

И так, давайте далеко не отходя от кассы, сразу рассмотрим пример, который я оставил в конце прошлой публикации.

#include <iostream>
#include <string>

using namespace std;

int GetID(){
    string Re = "19";
    return stoi(Re);
}

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    int ID = GetID();
    cout << "ID пользователя: " << ID << endl;
    
    return 0;
}

Что мы тут видим? Мы видим пример реализации функции, которая откуда то получает ID пользователя. И мы представили ситуацию, когда нам вернулось число в виде строки. На самом деле, когда мы перейдём к более приближенным к реальности примерам, мы увидим, что такая ситуация — вполне штатная и сталкиваться с ней вы будете с завидной регулярностью. И если попытаться вернуть число в виде строки — мы просто получим вот такую ошибку:

Пример ошибки с неверным типом возвращаемой переменной

На самом деле, если постараться, то можно заставить компилятор самостоятельно исправлять подобные ошибки, но чуть позже я покажу пример, почему так делать не стоит.

И так, что делать, чтоб преобразовать число в виде строки, в число, в виде числа? Просто воспользоваться функцией stoi(). Обратите внимание, что перед тем, как воспользоваться функцией, нужно убедиться, что в строке нет ничего, кроме цифр. Конечно, функция может, к примеру, обрезать пробельные символы или символы табуляции, но никак не строки. Т.е.:

Теперь давайте рассмотрим такой вариант:

Теперь давайте рассмотрим другой вариант:

#include <iostream>
#include <string>

using namespace std;

float GetInt(){
    float Re = 18.99;
    cout << "Передаём число: " << Re << endl;
    return Re;
}

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    int Get = GetInt();

    cout << "Получаем число: " << Get << endl;
    
    return 0;
}

Сразу запустим и посмотрим, что получаем: 

Пример неявного преобразования типов в языке С++

Как так получилось, что передавали 18.99, почти 19, а получили ровно 18? Думаю те, кто внимательно читал уроки и смотрел код, уже заметили, что в функции GetInt() была создана переменная с типом float, его же функция и вернула, но вот в main(), переменная имеет тип int, который меньше, чем float. По этому в данной переменной места для дробной части просто не хватило. Если сказать проще, тут произошло не явное преобразование типа. И это плохо. Давайте Расскажу пример, когда это может быть плохо.

К примеру, представьте себе ситуацию, когда мы написали программу, которая должна контролировать температуру в помещении, в конфиг файле вы написали, что считывание температуры должно происходить раз в 1,9 секунды. Но из за такой вот ошибки, считывание будет проходить почти в два раза чаще, раз в секунду и вы наверняка, потратите не один час времени в поисках причины, что же не так.

Разумеется, если рассматривать пример с секундами и температурой, исправление будет выглядеть просто. Мы просто в функции main(), строчку int Get = GetInt(); заменим на строчку float Get = GetInt();. Но что делать в ситуации, когда нам нужно именно преобразовать? Сделать это достаточно просто.

#include <iostream>
#include <string>

using namespace std;

float GetInt(){
    float Re = 18.99;
    cout << "Передаём число: " << Re << endl;
    return Re;
}

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    float Get = (int) GetInt();

    cout << "Получаем число: " << Get << endl;
    
    return 0;
}

Как видим, изменилась всего одна строка:  float Get = (int) GetInt();

Но при этом, поведение программы — осталось прежним! Так зачем было менять, спросите вы? А менять — надо! Дело в том, что благодаря добавленному оператору (int), вы сами видите, что функция возвращает другой тип данных, который преобразуется в int. Таким образом вы сами подстраховываете себя от забывчивости. Но что более важно, этим действием, вы говорите компилятору, что вкурсе несоответствия типов и хотите, чтоб он его преобразовал, не выдавая предупреждений.

Но остаётся ещё одна проблема. В данном случае, дробная часть — просто обрезается. Но можно ли сделать, чтоб преобразование происходило более умно? На самом деле — можно. К примеру, воспользовавшись функцией round().

#include <iostream>
#include <string>
#include <math.h>

using namespace std;

float GetInt(){
    float Re = 18.99;
    cout << "Передаём число: " << Re << endl;
    return Re;
}

int main(){
    setlocale(LC_ALL, "ru_RU.UTF-8");
    float Get = round(GetInt());

    cout << "Получаем число: " << Get << endl;
    
    return 0;
}

На самом деле, для округления значений до целого есть целых три функции: round, roundf, roundl, которыми можете воспользоваться в разных ситуациях. Подробнее о них написано тут.

Но обратите внимание. Для того, чтоб воспользоваться ими — нам нужно подключить ещё одну библиотеку. Написать в начале файла: #include <math.h>. И думаю теперь, когда их уже у нас стало три штуки, давайте наверное к ним и перейдём, давайте в следующей публикации уже поговорим о том, что это за магические строчки, которые помогают подключать магические функции, как они выглядят изнутри, и что более важно, попробуем сами написать что то, что можно подключить в виде магической строки.

Публикация относится к тематической подборке: «Уроки C++»

В данной подборке вы по шагам узнаете о увлекательном мире С++ и узнаете, на сколько глубока кроличья нора. Узнаете, для чего используется этот язык программирования, что с его помощью можно сделать и научитесь самостоятельно создавать самые сложные программы...

Понравилась публикация? Поделись ей с друзьями!

Понравился сайт? Подпишьсь на нас в соцсетях!

Мы в TelegramМы ВконтактеМы в ТвиттерМы на фейсбукМы в одноклассниках
Опубликовать
Загрузка рекомендуемых публикаций