#cpp #теория
Читаю сейчас "Discovering Modern C++", и есть там одно место, где автор пишет, что
в С++ есть четыре оператора приведения (всем знакомые ..._cast) и унаследованный из
C оператор (type)expr.
В связи с этим очередной теоретический вопрос: автор забыл о приведении type(expr)
или это приведение вообще говоря не является приведением, по сути являясь созданием
объекта типа type из expr? ну, или применением оператора преобразования типа? Ведь
вроде бы тут говорится, что это тоже преобразование типа?
И еще - а есть ли вообще разница между преобразованием (conversion) и приведением
(cast) или это синонимы?
И еще о лингвистике :) - у него четко различаются casting Up (от производного к базовому)
и casting Down (понятно, наоборот)... Но что-то я в нашей литературе таких терминов
раньше не встречал?
Ответы
Ответ 1
В связи с этим очередной теоретический вопрос: автор забыл о приведении type(expr) Это можно считать приведением(так пишет Майерс и другие называют это приведением), но в стандарте это не входит в список операторов приведения(cast operators). Т.е. формально, данный синтаксис не является синтаксисом приведения. Он в стандарте имеет своё имя: functional notation. В сущности, это создание объекта инициализированного expr. Это вызов конструктора. И еще - а есть ли вообще разница между преобразованием (conversion) и приведением (cast) или это синонимы? Первое это существительное, второе — глагол(чаще). Нет, разницы, с точки зрения языка, — нет. Но что-то я в нашей литературе таких терминов раньше не встречал? Я нашу литературу давно не читаю, но если это перевод книги, в которой есть up-casting и down-casting, это не может быть не переведено. Из стандарта про синтаксис из вопроса: [expr.type.conv]p2 A simple-type-specifier (7.1.6.2) or typename-specifier (14.6) followed by a parenthesized expression-list constructs a value of the specified type given the expression list. If the expression list is a single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4) <...> Где corresponding cast expression это (T)expressionОтвет 2
Выражение type(expr) не является приведением. Это создание нового объекта на основе expr, иногда может интерпретироваться как создание новой переменной int(a); // создание переменной a unsigned b = unsigned(a); // создание нового объекта из a и инициализация b его значением Разница между преобразованием и приведением есть. Приведение не влечёт за собой выполнения никакого кода, при преобразовании будет выполненный определённый код. При использовании кастов из С++ необходимо прочитать в справке, какие конкретно действия будут выполнены.Ответ 3
В Мэйерс. Эффективное использование C++ автор считает конструкции (T)e и T(e) не имеющими "ощутимого различия, просто скобки расставляются по-разному". Однако в "Страуструп. Язык программирования C++. Специальное издание. - М.;СПб.: Издательство БИНОМ - Невский Диалект, 2002" дается более сложное описание. T(e) - создание значения типа T из значения e с помощью конструктора. Для встроенных типов эта запись эквивалента (T)e. Однако все-таки не до конца: преобразование указателей с ее помощью невозможно - написать (char *)2 можно, а char*(2) нельзя. Поэтому, на мой взгляд, это все-таки немного разные конструкции - приведение (T)e будет компилироваться всегда, в отличие от T(e).Ответ 4
Преобразование типов может быть как явным, так и неявным. Явное преобразование называется приведением (casting). Чтобы в этом убедиться достаточно посмотреть на раздел Index Стандарта и увидеть там такие сноски: conversion explicit type, see casting explicit type conversion, see casting type conversion, explicit, see casting Явное преобразование типов описано в двух параграфах СтандартаC++14, названия которых начинаются с фразы Explicit type conversion, но имеют разное окончание: 5.2.3 (functional notation); 5.4 (cast notation). При этом в п. 5.4/2 сказано: An explicit type conversion can be expressed using functional notation (5.2.3), a type conversion operator (dynamic_cast, static_cast, reinterpret_cast, const_cast), or the cast notation. Т.о. явное преобразование может быть выражено через: функциональную нотацию: T(e) оператор преобразования типов: dynamic_cast, static_cast и т.д. нотацию приведения: (T)e Функциональная нотация (относительно фундаментальных типов) разрешена только для простых спецификаторов типа (char, double, int и т.д.), но уже не будет работать с типами, записанными более чем одним словом (unsigned char, long double, signed int и т.д.). Для классов функциональная нотация приводит к вызову конструктора соответствующего класса. При использовании нотации приведения (Си-нотации) компилятор пытается выполнить следующие преобразования в указанном порядке: const_cast static_cast static_cast с последующим const_cast reinterpret_cast reinterpret_cast с последующим const_cast В итоге будет выбран первый вариант, который удовлетворит требованиям соответствующего оператора. По возможности следует избегать в коде на C++ использования приведения в стиле Си. И отдавать предпочтение соответствующим castам для более четкого выражения своих намерений.
Комментариев нет:
Отправить комментарий