в каком случае лучше всего использовать приведение типов данных

Приведение типов

Будучи на конференции Qt Developer Days 2010 я узнал, что одним из самых популярных вопросов на собеседовании в разные зарубежные компании, работающие с Qt библиотекой, является вопрос о различиях в способах приведения типов в C++. Поэтому здесь я рассмотрю основные различия между static_cast, dynamic_cast, const_cast, reinterpret_cast, C-style cast, qobject_cast и qvariant_cast

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

Используется для динамического приведения типов во время выполнения. В случае неправильного приведения типов для ссылок вызывается исключительная ситуация std::bad_cast, а для указателей будет возвращен 0. Использует систему RTTI (Runtime Type Information). Безопасное приведение типов по иерархии наследования, в том числе для виртуального наследования.

Пожалуй самое простое приведение типов. Снимает cv qualifiers — const и volatile, то есть константность и отказ от оптимизации компилятором переменной. Это преобразование проверяется на уровне компиляции и в случае ошибки приведения типов будет выдано сообщение.

Приведение типов без проверки. reinterpret_cast — непосредственное указание компилятору. Применяется только в случае полной уверенности программиста в собственных действиях. Не снимает константность и volatile. применяется для приведения указателя к указателю, указателя к целому и наоборот.

Си-шный метод приведения типов. Пожалуй самый нежелательный способ приведения типов. Страуструп пишет:
«Например, что это значит выражение — x = (T)y;. Мы не знаем. Это зависит от типа T, типов x и y. T может быть названием типа, typedef или может быть параметр template-а. Может быть, х и у являются скалярными переменными и Т представляет собой значение преобразования. Может быть, х объекта класса, производного от класса Y и Т — нисходящее преобразование. По этой причине программист может не знать, что он делает на самом деле.»
Вторая причина нежелательного использования приведения типов в C-style — трудоемкость процесса поиска мест приведения типов.

Приводит объект QObject* к типу TYPE если объект типа объекта TYPE или тип наследует от TYPE иначе возвращает 0. qobject_cast от 0 также дает 0. Необходимое условие. Класс должен наследовать от QObject и содержать в себе макрос Q_OBJECT. Функция ведет себя аналогично стандартному dynamic_cast, но при этом не использует RTTI. Вот как описана данная функция в Qt 4.7.0:

Итак, что тут происходит:

Во-первых если не определены QT_NO_MEMBER_TEMPLATES (определяется только в том случае, если используется версия Microsoft Visual Studio ниже 2002) и QT_NO_QOBJECT_CHECK (определяется в случае использования версии Microsoft Visual Studio ниже 2003), то происходит проверка наличия макроса Q_OBJECT в объявлении класса. И после этого выполняется непосредственно само преобразование — сначала получаем статический объект класса QMetaObject, который называется staticMetaObject, у которого вызывается метод cast, который возвращает const_cast переданного ему объекта, попутно проверяя наследуется ли данный объект от QObject. Далее полученному объекту делается static_cast и возвращается результат.

Приводит объект класса QVariant к нужному классу. Функция аналогична функции qVariantValue.

Рассмотрим, что происходит внутри:

В первой секции кода производится получение идентификатора класса через метасистему Qt. В том случае если класс не зарегистрирован через Q_DECLARE_METATYPE, компиляция кода с приведением к этому типу выдаст ошибку. Далее, если тип объекта, полученный от метасистемы совпадает с типом в значении QVariant, производится reinterpret_cast содержимого объекта, если идентификатор класса не является встроенным типом и его id не совпадает с заложенным в значении QVariant, то возвращается TYPE(). Для случаев, когда мы приводим к встроенному типу, вызывается функция qvariant_cast_helper, которая вызывает в свою очередь функцию convert, адрес которой хранится в структуре Handler. В ней уже осуществляется приведение способом подходящим для типа TYPE. Если конвертация не удалась возвращается объект TYPE()

UPD: Спасибо BaJlepa:
1. const_cast также умеет добавлять cv-квалификаторы
2. для преобразования указателей лучше использовать двойной static_cast через void* вместо reinterpret_cast, потому как такое преобразование позволяет быть уверенным в том, что только pointer-ы участвуют в приведении

Источник

Тест по дисциплине «Основы алгоритмизации и программирования»

Ищем педагогов в команду «Инфоурок»

1. Какому зарезервированному слову программа передаёт управление в случае, если значение переменной или выражения оператора switch не совпадает ни с одним константным выражением?

2. Какой оператор не допускает перехода от одного константного выражения к другому?

4. Укажите правильное определение функции main в соответствии со спецификацией стандарта ANSI

5. Какую функцию должны содержать все программы на С++?

6. До каких пор будут выполняться операторы в теле цикла while (x

Пока х меньше или равен 100

Пока х строго меньше 100

7. Какое значение, по умолчанию, возвращает программа операционной системе в случае успешного завершения?

Программа не возвращает значение.

8. Структура объявления переменных в С++

9. Программа, переводящая входную программу на исходном языке в эквивалентную ей выходную программу на результирующем языке, называется:

10. Название С++ предложил

11. Каков результат работы следующего франмента кода?

case 2: cout Привет мир «;

12. Какое значение будет напечатано?

int main(int argc, char** argv)

13. Оператор вывода cout может печатать несколько значений или переменных в одной команде, используя следующий синтаксис:

cout Привет «, name, «n»;

cout Привет » + name + «n»;

14. Какое значение будет напечатано, в результате выполнения программы?

ничего не напечатается, программа вообще не будет работать

15. Тело оператора выбора if, будет выполняться. если его условие:

16. Укажите блок кода, в котором переменная y доступна.

int main(int argc, char** argv)

17. Что появится на экране, после выполнения этого фрагмента кода?

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

результат не может быть заранее определен

19. Какое из следующих значений эквивалентно зарезервированному слову true?

Все варианты ответов

20. Это значение 5.9875e17 может быть сохранено в переменной, типа

21. Вывод данных в C++

22. В каком случае лучше всего использовать приведение типов данных?

во всех выше указанных случаях

чтобы разрешить программе использовать только целые числа

чтобы изменить тип возвращаемого значения функции

при делении двух целых чисел, для того, чтобы вернуть результат с плавающей точкой

23. Какой тип данных имеет переменная ARGV?

24. Что будет напечатано на экране, после выполнения этого кода?

int main(int argc, char** argv)

25. Какая строка содержит зарезервированные слова языка программирования С++?

sizeof, const, typedef, static, voided, enum, struct, union

char, int, float, doubled, short, long, unsigned, signed

if, else, for, while do, switch, continue, break

defaulted, goto, return, extern, private, public, protected

const variable = value;

const type variable := value;

const type variable = value;

2. Укажите объектно-ориентированный язык программирования

Все варианты ответов

int i, N = 40;for(i = 0; i

int i, N = 20;for(i = 0; i

int i, N = 20;for(i = 20; i

int i, N = 20;for(i = 19; i

4. Какие служебные символы используются для обозначения начала и конца блока кода?

5. Чтобы подключить заголовочный файл в программу на С++, например iostream необходимо написать:

#include <>; с iostream.h внутри скобок

#include <> с iostream внутри скобок

6. Какими знаками заканчивается большинство строк кода в Си++?

у цикла нет условия

8. Что будет напечатано?

Ошибка компиляции в строке 10

9. Какой из перечисленных типов данных не является типом данных в С++?

11. Результат выполнения следующего фрагмента кода: 54

нет правильного ответа

12. Какие преобразования типов данных не возможны без потери данных?

все перечисленные преобразования не возможны

13. Укажите операцию, приоритет выполнения которой ниже остальных.

14. Что будет напечатано, после выполнения этого кода: cout

15. Укажите неправильно записанную операцию отношения

все операторы записаны правильно

16. Результат выполнения следующего фрагмента кода: cout

17. В каком случае можно не использовать фигурные скобочки в операторе выбора if?

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

если в теле оператора if два и более операторов

нет правильного ответа

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

18. Ввод данных в C++

19. Какое ключевое слово указывает, что целая переменная не может принимать отрицательные значения?

нет такого зарезервированного слова

20. Преобразование целочисленной переменной value в ASCII эквивалент

22. Какое значение будет содержать переменная y?

int main(int argc, char** argv)

int y = sizeof(x) / sizeof(int);

23. Укажите правильный вызов функции, предпологается, что функция была объявлена ранее.

24. Что такое ARGV[0]?

ARGV[0] нигде не используется

первый аргумент, который передается в программу из командной строки

25. Можно ли гарантировать, что объявленная встроенная функция действительно является встроенной?

можно с уверенностью гарантировать, что объявленная вами функция как встроенная, действительно будет встроенной

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

1. Язык программирования C++ разработал

2. Какие среды программирования (IDE) предназначены для разработки программных средств?

MVS, Code::Blocks, QT Creator, AutoCAD, Eclipse

MVS, NetBeans, QT Creator, RAD Studio, Dev-C++

MVS, Code::Blocks, QT Creator, RAD Studio, MathCAD

4. Чему будет равна переменная a, после выполнения этого кода int a; for(a = 0; a

5. Цикл с постусловием?

6. Укажите правильную форму записи цикла do while

// форма записи оператора цикла do while:

do // начало цикла do while

// форма записи оператора цикла do while:

do // начало цикла do while

while (/*условие выполнения цикла*/); // конец цикла do while

// форма записи оператора цикла do while:

do // начало цикла do while

while (/*условие выполнения цикла*/) // конец цикла do while

7. Какой из ниже перечисленных операторов, не является циклом в С++?

8. Общий формат оператора множественного выбора – switch

case constant1, case constant2: statement1; [break;]

case constantN: statementN; [break;]

[default: statement N+l;]

case constant1: statement1; [break;]

case constant2: statement2; [break;]

case constantN: statementN; [break;]

[default: statement N+l;]

case constant1: statement1; [break;]

case constant2: statement2; [break;]

case constantN: statementN; [break;]

9. Цикл с предусловием?

10. Простые типы данных в С++.

целые – bool, вещественные – float или double, символьные – string

целые – int, вещественные – float или double, символьные – char

целые – int, вещественные – float или double, символьные – string

целые – int, вещественные – float или real, символьные – char

11. Укажите операцию, приоритет выполнения которой больше остальных

13. Какое значение будет содержать переменная х?

14. Какой заголовочный файл следует подключить, чтобы можно было пользоваться приведением типов данных?

15. Переменная x может быть доступна в другом блоке программы?

int main(int argc, char** argv)

16. Если условие оператора выбора ложное, то:

выполняется тело оператора выбора

выполняется следующий оператор, сразу после оператора if

программа завершает работу

17. Логическая операция с большим приоритетом выполнения

19. Укажите правильное приведение типа данных!

20. Почему приведение типов данных может быть не безопасно.

нет никаких опасностей

Вы можете навсегда изменить значение переменной

только для ложного условия

только для истинного условия

для истинного и ложного условий

условное выражение if

if условное выражение

if ( условное выражение )

23. Какая из переменных хранит количество аргументов, передаваемых в программу?

24. Для чего используются встроенные функции?

Чтобы уменьшить размер программы

Для увеличения скорости работы программы

Для удаления ненужных функций

Для упрощения файла с исходным кодом

25. Что будет напечатано на экране, после выполнения этого кода?

int foo(int x, int y)

double foo(double x, double y)

int main(int argc, char** argv)

в каком случае лучше всего использовать приведение типов данных. Смотреть фото в каком случае лучше всего использовать приведение типов данных. Смотреть картинку в каком случае лучше всего использовать приведение типов данных. Картинка про в каком случае лучше всего использовать приведение типов данных. Фото в каком случае лучше всего использовать приведение типов данных

Курс повышения квалификации

Дистанционное обучение как современный формат преподавания

в каком случае лучше всего использовать приведение типов данных. Смотреть фото в каком случае лучше всего использовать приведение типов данных. Смотреть картинку в каком случае лучше всего использовать приведение типов данных. Картинка про в каком случае лучше всего использовать приведение типов данных. Фото в каком случае лучше всего использовать приведение типов данных

Курс повышения квалификации

Современные педтехнологии в деятельности учителя

в каком случае лучше всего использовать приведение типов данных. Смотреть фото в каком случае лучше всего использовать приведение типов данных. Смотреть картинку в каком случае лучше всего использовать приведение типов данных. Картинка про в каком случае лучше всего использовать приведение типов данных. Фото в каком случае лучше всего использовать приведение типов данных

Курс профессиональной переподготовки

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

в каком случае лучше всего использовать приведение типов данных. Смотреть фото в каком случае лучше всего использовать приведение типов данных. Смотреть картинку в каком случае лучше всего использовать приведение типов данных. Картинка про в каком случае лучше всего использовать приведение типов данных. Фото в каком случае лучше всего использовать приведение типов данных

Номер материала: ДБ-1636687

Международная дистанционная олимпиада Осень 2021

Не нашли то что искали?

Вам будут интересны эти курсы:

Оставьте свой комментарий

Авторизуйтесь, чтобы задавать вопросы.

в каком случае лучше всего использовать приведение типов данных. Смотреть фото в каком случае лучше всего использовать приведение типов данных. Смотреть картинку в каком случае лучше всего использовать приведение типов данных. Картинка про в каком случае лучше всего использовать приведение типов данных. Фото в каком случае лучше всего использовать приведение типов данных

В школе в Пермском крае произошла стрельба

Время чтения: 1 минута

в каком случае лучше всего использовать приведение типов данных. Смотреть фото в каком случае лучше всего использовать приведение типов данных. Смотреть картинку в каком случае лучше всего использовать приведение типов данных. Картинка про в каком случае лучше всего использовать приведение типов данных. Фото в каком случае лучше всего использовать приведение типов данных

Треть школ и пятая часть детских садов в России являются инклюзивными

Время чтения: 1 минута

в каком случае лучше всего использовать приведение типов данных. Смотреть фото в каком случае лучше всего использовать приведение типов данных. Смотреть картинку в каком случае лучше всего использовать приведение типов данных. Картинка про в каком случае лучше всего использовать приведение типов данных. Фото в каком случае лучше всего использовать приведение типов данных

Рособрнадзор оставил за регионами решение о дополнительных школьных каникулах

Время чтения: 1 минута

в каком случае лучше всего использовать приведение типов данных. Смотреть фото в каком случае лучше всего использовать приведение типов данных. Смотреть картинку в каком случае лучше всего использовать приведение типов данных. Картинка про в каком случае лучше всего использовать приведение типов данных. Фото в каком случае лучше всего использовать приведение типов данных

ВШЭ перейдет на удаленку до конца года

Время чтения: 1 минута

в каком случае лучше всего использовать приведение типов данных. Смотреть фото в каком случае лучше всего использовать приведение типов данных. Смотреть картинку в каком случае лучше всего использовать приведение типов данных. Картинка про в каком случае лучше всего использовать приведение типов данных. Фото в каком случае лучше всего использовать приведение типов данных

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

Время чтения: 1 минута

в каком случае лучше всего использовать приведение типов данных. Смотреть фото в каком случае лучше всего использовать приведение типов данных. Смотреть картинку в каком случае лучше всего использовать приведение типов данных. Картинка про в каком случае лучше всего использовать приведение типов данных. Фото в каком случае лучше всего использовать приведение типов данных

Школьников не планируют переводить на удаленку после каникул

Время чтения: 1 минута

Подарочные сертификаты

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

Все материалы, размещенные на сайте, созданы авторами сайта либо размещены пользователями сайта и представлены на сайте исключительно для ознакомления. Авторские права на материалы принадлежат их законным авторам. Частичное или полное копирование материалов сайта без письменного разрешения администрации сайта запрещено! Мнение администрации может не совпадать с точкой зрения авторов.

Источник

Преобразования типов и безопасность типов

В этом документе описаны распространенные проблемы преобразования типов и описывается, как избежать их использования в коде C++.

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

Неявные преобразования типов

Если выражение содержит операнды различных встроенных типов и явные приведения отсутствуют, компилятор использует встроенные стандартные преобразования для преобразования одного из операндов, чтобы типы совпадали. Компилятор пытается выполнить преобразования в четко определенной последовательности, пока она не завершится успешно. Если выбранное преобразование является повышением, компилятор не выдает предупреждение. Если преобразование является узким, компилятор выдает предупреждение о возможной утрате данных. Происходит ли фактическая потери данных, зависит от фактических значений, но рекомендуется считать это предупреждение как ошибку. Если включен определяемый пользователем тип, компилятор пытается использовать преобразования, указанные в определении класса. Если не удается найти допустимое преобразование, компилятор выдает ошибку и не компилирует программу. Дополнительные сведения о правилах, регулирующих стандартные преобразования, см. в разделе стандартные преобразования. Дополнительные сведения о пользовательских преобразованиях см. в разделе пользовательские преобразования (C++/CLI).

Расширяющие преобразования (продвижение)

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

Сужающие преобразования (приведение)

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

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

В следующем примере кода показаны некоторые неявные сужающие преобразования и предупреждения, которые возникают компилятором.

Преобразования со знаком — без знака

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

Преобразования указателей

Явные преобразования (приведения)

С помощью операции приведения можно указать компилятору преобразовать значение одного типа в другой тип. В некоторых случаях компилятор вызовет ошибку, если эти два типа полностью не связаны, но в других случаях не вызывает ошибку, даже если операция не является строго типизированной. Используйте приведение с осторожностью, так как любое преобразование из одного типа в другой является потенциальным источником ошибок программы. Однако иногда требуется выполнить приведения, а не все приведения являются опасными. Одно эффективное использование приведения заключается в том, что в коде выполняется понижающие преобразования и известно, что преобразование не приводит к созданию неверных результатов в программе. Фактически, это говорит компилятору о том, что вы делаете, а также о том, что вы выполняете предупреждения. Другой способ заключается в приведении из класса указателя на класс, производный от указатель на базовый. Другой способ — приведение к переменной постоянной, чтобы передать ее в функцию, для которой требуется аргумент, не являющийся константой. Большинство этих операций приведения к некоторым рискам требует определенного риска.

В программировании в стиле C для всех типов приведений используется один и тот же оператор приведения в стиле C.

Этот оператор приведения не используется так часто, как другие, и не гарантирует перенос в другие компиляторы.

Дополнительные сведения см. в разделе reinterpret_cast оператор.

Источник

Руководство по программированию на C#. Приведение и преобразование типов

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

Пользовательские преобразования. Такие преобразования выполняются специальными методами, которые можно определить для включения явных и неявных преобразований между пользовательскими типами без связи «базовый класс — производный класс». Дополнительные сведения см. в разделе Операторы пользовательского преобразования.

Преобразования с использованием вспомогательных классов. Чтобы выполнить преобразование между несовместимыми типами, например целыми числами и объектами System.DateTime или шестнадцатеричными строками и массивами байтов, можно использовать классы System.BitConverter и System.Convert, а также методы Parse встроенных числовых типов, такие как Int32.Parse. Дополнительные сведения см. в руководствах по преобразованию массива байтов в значение типа int, преобразованию строки в число и преобразованию из шестнадцатеричных строк в числовые типы.

Неявные преобразования

Полный список всех неявных числовых преобразований см. в разделе Таблица неявных числовых преобразований в статье Встроенные числовые преобразования.

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

Явные преобразования

Тем не менее если преобразование нельзя выполнить без риска потери данных, компилятор требует выполнения явного преобразования, которое называется приведением. Приведение — это способ явно указать компилятору, что необходимо выполнить преобразование и что вам известно, что может произойти потеря данных или приведение может завершиться сбоем во время выполнения. Чтобы выполнить приведение, укажите тип, в который производится приведение, в круглых скобках перед преобразуемым значением или переменной. В следующей программе выполняется приведение типа double в int. Программа не будет компилироваться без приведения.

Полный список всех поддерживаемых явных числовых преобразований см. в разделе Таблица явных числовых преобразований в статье Встроенные числовые преобразования.

Для ссылочных типов явное приведение является обязательным, если необходимо преобразовать базовый тип в производный тип:

Операция приведения между ссылочными типами не меняет тип времени выполнения базового объекта; изменяется только тип значения, который используется в качестве ссылки на этот объект. Дополнительные сведения см. в разделе Полиморфизм.

Исключения преобразования типов во время выполнения

В некоторых преобразованиях ссылочных типов компилятор не может определить, будет ли приведение допустимым. Есть вероятность, что правильно скомпилированная операция приведения завершится сбоем во время выполнения. Как показано в следующем примере, приведение типа, завершившееся сбоем во время выполнения, вызывает исключение InvalidCastException.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *