Стили синтаксиса приведения C++

Вопрос, связанный с обычным приведением, static_cast и dynamic_cast:

Какой стиль синтаксиса приведения вы предпочитаете в C++?

  • Синтаксис приведения в стиле C: (int)foo
  • Синтаксис приведения в стиле C++: static_cast<int>(foo)
  • синтаксис конструктора: int(foo)

Они могут не переводиться в точно такие же инструкции (не так ли?), но их эффект должен быть таким же (правильно?).

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

Что вы думаете?


person palm3D    schedule 28.08.2008    source источник


Ответы (10)


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

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

Как отмечает palm3D:

Я нахожу синтаксис приведения в стиле C++ слишком многословным.

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

Синтаксис конструктора (официальное название: приведение в стиле функции) семантически то же самое, что и приведение в стиле C, и его также следует избегать (за исключением инициализации переменных при объявлении) по тем же причинам. Можно спорить, должно ли это быть верным даже для типов, которые определяют пользовательские конструкторы, но Мейерс утверждает, что в Effective C++ даже в этих случаях вы должны воздерживаться от их использования. Проиллюстрировать:

void f(auto_ptr<int> x);

f(static_cast<auto_ptr<int> >(new int(5))); // GOOD
f(auto_ptr<int>(new int(5));                // BAD

Здесь static_cast вызовет конструктор auto_ptr.

person Konrad Rudolph    schedule 28.08.2008
comment
Интересно, сколько раз вы искали приведение в своем коде с помощью автоматизированного инструмента... - person Blindy; 05.12.2010
comment
@Вслепую: это случается. Я уже сделал это. Помните, что в C++, в отличие от некоторых других языков (Java, C#), обычно можно программировать без приведения типов. Каждое явное приведение типов в вашем коде является потенциальным недостатком дизайна. Выявление приведения типов в коде C++ — важный шаг в рефакторинге. В C# было бы, конечно, смешно искать приведения в коде — они повсюду! - person Konrad Rudolph; 05.12.2010
comment
@Konrad: И, конечно же, Java и C# также имеют свой собственный эквивалент dynamic_cast, который является особым приведением. - person Puppy; 29.05.2012
comment
какой из различных бросков используется. это просто. он всегда использует приведение стиля c. не нужно пытаться перевести его в приведение в стиле С++ - person Johannes Schaub - litb; 20.10.2012
comment
в примере с auto_ptr, разве плохой вызов не создает временный auto_ptr, а не пытается привести указатель? - person user666412; 03.12.2013
comment
@user666412 user666412 Я думаю, вы неправильно понимаете, что делает приведение: оно также создает временный auto_ptr. В приведении нет ничего особенного в этом отношении, меняется только синтаксис. - person Konrad Rudolph; 03.12.2013
comment
В вашем ответе есть две проблемы: 1) вы упоминаете две основные причины, но перечисляете три. :) +1 - person augustin; 22.09.2015
comment
Разве // GOOD здесь не ерунда? Было бы ужасно написать что-то вроде static_cast<std::string>("hello") вместо std::string("hello") или любую подобную конструкцию объекта пользовательского типа. - person Ruslan; 08.01.2016
comment
@Ruslan Ну, несколько авторитетов в C ++ с вами не согласны. - person Konrad Rudolph; 09.01.2016
comment
Тогда у кого-то не должно возникнуть проблем с тем, чтобы точно указать, где и с какой формулировкой (а) Саттер и (б) остальные несколько авторитетных специалистов по С++ сказали что-либо подобное, потому что это звучит как (i) новость и (ii) бессмыслица для меня. - person underscore_d; 12.09.2018
comment
@underscore_d В своем ответе я процитировал один из этих авторитетов. Что бы это ни стоило, стиль определенно не прижился, а также несколько устарел с инициализацией юниформ. - person Konrad Rudolph; 12.09.2018
comment
Какое облегчение! На что я надеялся, так это на то, что отрывок, в котором Саттер сказал это, был где-то выдернут, чтобы я мог прочитать его рассуждения, но я полагаю, что нет? (по крайней мере, не все эти годы/издания позже) Та или иная актуальная, конкретная цитата. Но да, это не имеет значения, если это правильно заменено. - person underscore_d; 13.09.2018
comment
Одной из очень веских причин избегать приведения типов в функциональном стиле является наиболее неприятный синтаксический анализ. Подумайте об этом: int a = 42; MyDoubleClass d(double(a)); Что такое d? Ответ: функция с именем d, которая принимает double в качестве параметра и возвращает объект типа MyDoubleClass. - person callyalater; 12.12.2018

Согласно Страуструпу:

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

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

person hometoast    schedule 28.08.2008

Что касается этой темы, я следую рекомендациям Скотта Мейерса (Более эффективный C++, пункт 2. Предпочтение приведения типов в стиле C++).

Я согласен с тем, что приведение типов в стиле C++ многословно, но это то, что мне в них нравится: их очень легко обнаружить, и они облегчают чтение кода (что более важно, чем написание).

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

person Jérôme    schedule 28.08.2008

Я использую static_cast по двум причинам.

  1. Совершенно ясно, что происходит. Я не могу читать это, не понимая, что происходит актерский состав. С помощью слепков в стиле С вы можете скользить взглядом по нему без паузы.
  2. Легко найти каждое место в моем коде, где я выполняю кастинг.
person Bill the Lizard    schedule 28.08.2008

Определенно в стиле C++. Дополнительный ввод поможет предотвратить кастинг, когда вы не должны :-)

person Ben Collins    schedule 28.08.2008

Синтаксис конструктора. C++ — это объектно-ориентированный язык, конструкторы существуют, я их использую. Если вы чувствуете необходимость аннотировать эти преобразователи, вы должны сделать это для каждого типа, а не только для встроенных. Возможно, вы используете ключевое слово 'explicit' для преобразователей, но синтаксис клиента точно имитирует синтаксис ctor для встроенных типов. Быть greppable, это может быть правдой, но какой большой сюрприз, что ввод большего количества символов облегчает поиск. Зачем относиться к ним как к особенным? Если вы пишете математические формулы с большим количеством int/unsigned/... в и из double/float - графика - и вам нужно каждый раз писать static_cast, вид формулы становится загроможденным и очень нечитаемым. И в любом случае это тяжелая битва, так как много раз вы конвертируете, даже не замечая этого. Для понижения указателей я использую static_cast, поскольку, конечно, по умолчанию не существует ctor, который мог бы это сделать.

person QBziZ    schedule 23.12.2016

Синтаксис приведения в стиле C, без проверки ошибок. Синтаксис приведения в стиле C++ выполняет некоторые проверки. При использовании static_cast, даже если он не выполняет проверку, по крайней мере, вы знаете, что здесь следует быть осторожным.

person CiNN    schedule 28.08.2008
comment
static_cast всегда проверяет совместимость исходного и целевого типов. (Это не может защитить пользователей от их ошибки, если они преобразуют базовый тип в производный тип, которого у него на самом деле нет, но это их вина.) - person underscore_d; 13.05.2017

Приведение в стиле C — худший путь. Его труднее увидеть, он не поддается восприятию, объединяет разные действия, которые не следует объединять, и не может делать все, что могут делать приведения типов в стиле C++. Они действительно должны были удалить приведения в стиле C из языка.

person DrPizza    schedule 28.08.2008

В настоящее время мы повсеместно используем приведения в стиле C. Я задал другой вопрос о кастинге, и теперь я вижу преимущество использования static_cast, хотя бы по той причине, что он "greppable" (мне нравится этот термин). Я, вероятно, начну использовать это.

Мне не нравится стиль C++; это слишком похоже на вызов функции.

person Graeme Perrow    schedule 28.08.2008
comment
выглядит так, как будто вызов функции может быть приятным, он позволяет вам иметь служебные функции, которые используют один и тот же стиль, например, общий lexical_cast для преобразования из строк ‹-› числовых типов. Но это всего лишь мнение. - person Evan Teran; 04.04.2010

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

person CAH    schedule 26.02.2012