броски стиля c или броски стиля c ++

21

Итак, что вы используете?

int anInt = (int)aFloat;

или

int anInt = static_cast<int>(aFloat);
// and its brethren

И, что более важно, почему?

bastibe
источник

Ответы:

45

Во-первых, поймите, что эти строки не эквивалентны .

int* anInt = (int*)aFloat; // is equivalent to

int* anInt = reinterpret_cast<int*>(aFloat); 

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

Разница важна, потому что использование static_cast будет запрашивать только базовый тип, в который «безопасно» конвертировать, где reinterpret_cast будет конвертировать во что угодно, возможно, просто отображая требуемый макет памяти в памяти данного объекта.

Таким образом, поскольку «фильтр» не тот же, использование конкретного приведения является более понятным и безопасным, чем использование C-преобразования, если вы полагаетесь на компилятор (или во время выполнения, если вы используете dynamic_cast), чтобы сказать вам, где вы сделали что-то не так , избегая C cast и reinterepret_cast.

Теперь, когда это стало более понятным, появилась другая вещь: static_cast, reinterpret_cast, const_cast и dynamic_cast легче искать .

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

Это "по замыслу". И это позволяет разработчику знать, где он мог бы сделать что-то лучше (полностью избегая приведений, если в этом нет особой необходимости) и где это хорошо, но это «документировано» в коде, «пометив» его как некрасивое.

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

Может быть, из-за того, что static_cast настолько уродлив и относительно труден для ввода, вы, скорее всего, дважды подумаете, прежде чем его использовать? Это было бы хорошо, потому что в современном C ++ приведение действительно можно избежать.

Источник: Бьярне Страуструп (создатель C ++)

Klaim
источник
2
Я бы понизил это, если бы у меня было еще несколько очков, но, к сожалению, я не могу. Приведения в стиле c НЕ эквивалентны reinterpret_cast. Посмотрим reinterpret_cast<int>(double);. Полностью возможно привести к двойному типу int с приведением в стиле c, но это не возможно сделать с reinterpret_cast. Я вижу, Тимбо уже указал вам на это, и вы сказали, что исправите это, но четыре года спустя это остается неверным. Тем не менее, я бы все равно понизил голос, если бы это было исправлено, поскольку есть совершенно веские причины, по которым нужно использовать приведение. Вот лучший ответ: stackoverflow.com/a/332086/3878168
Yay295
36

Приведение C ++ более ограничено (поэтому лучше выражайте свои намерения, упростите проверку кода и т. Д.). Их также намного легче искать, если вам когда-либо понадобится.

Брюс Стивенс
источник
10
... и они, скорее всего, сделают то, что вы собираетесь. ;-)
Macke
7
И их гораздо больше, чтобы печатать, давая вам еще одну причину, чтобы просто получить ваши правильные типы без необходимости приведения.
Майкл Кохне
7
И они уродливы как функция, делая очевидным, где в коде могут быть моменты улучшения или особые случаи, которые могут потребовать документации. - edit: вау я только что обнаружил я тоже ответил на этот вопрос! XD
Klaim
Теперь, почему я хотел бы искать их?
Дедупликатор
@Deduplicator Есть много причин, по которым вы можете захотеть узнать, где происходят преобразования в базе кода. Например, при поиске ошибок, которые могут быть связаны с кастингом (в частности, при кроссплатформенной разработке).
Klaim
13

Вариант C: приведение типа "C ++", потому что оно неотличимо от конструкции:

int anInt = int(aFloat);

или даже:

int anInt(aFloat);

Кроме этого, кроме этих тривиальных случаев с примитивами, которые хорошо понятны, я предпочитаю использовать x_cast <> вместо приведений в стиле C. Есть три причины, почему:

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

  • Они могут выполнять действия, которые не могут выполняться в стиле C (особенно в случае dynamic_cast <>, который может выполнять перекрестное приведение через ветви цепочки множественного наследования).

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

Каз Дракон
источник
7

Если вы пишете код на C, используйте C cast. При написании на C ++ используйте приведение C ++.

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

Я могу допустить, чтобы кто-то использовал (T *) NULL, хотя для принудительной перегрузки ...

Дойная корова
источник
7

У меня есть несколько правил о приведениях в стиле C / C ++:

  1. Отказ от применения const всегда должен использовать const_cast. По понятным причинам. К сожалению, мое правило об отмене применения const, заставляющего клавиатуру подниматься и ломать палец программиста, не было одобрено.
  2. Любой из махинаций в стиле битовых манипуляций, которые программисты используют при переходе к металлу, следует использовать reinterpret_cast. Это действительно тот тип приведения, которого нет у C: притвориться, что биты этого целого числа на самом деле являются битами с плавающей точкой. Это позволяет избежать неприятностей, как (int)(*(int*)(&floatVar)).
  3. Если вы введете слова « dynamic_cast», остановите и заново оцените вашу полиморфную иерархию классов и дизайн. Продолжайте переоценку дизайна иерархии классов, пока не сможете удалить эти слова.
  4. Не беспокойся static_cast.

Причина № 4 в том, что это не имеет значения. Обстоятельства, которые не вписываются в другие правила, либо очевидны, либо действительно низкоуровневы. Хорошо понятное преобразование простых типов, таких как int-to-float, не должно нуждаться в специальном синтаксисе. И если вы в глубоких, уродливых кишках чего-то, ну, вы в глубоких, уродливых кишках чего-то. Нет необходимости привлекать внимание к тому факту, что «здесь будут драконы», поскольку зубы, когти и огонь в значительной степени уже отдали его.

Николь Болас
источник
1
dynamic_castэто совершенно правильный инструмент. Я признаю, что это очень полезно, но это далеко от сатаны таких вещей, как глобальные переменные. Тем не менее, в первую очередь, я проголосовал против вас, потому что вы не ответили на вопрос , касающийся использования или не приведений типа C.
DeadMG
2
@DeadMG: я говорил о кастах в стиле C. Весь последний абзац оправдывает приведение в стиле C в пользу static_cast.
Никол Болас
«К сожалению, мое правило об отмене применения const, заставляющего клавиатуру подниматься и ломать палец программиста, не было одобрено». Технически это действительно допустимо для компилятора. Как это допустимо для компилятора, чтобы демоны вылетали из вашего носа .
Pharap
4

Как отмечают вышеприведенные посты, приведение C ++ (статическое) на практике немного безопаснее.

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

Просто чтобы узнать больше о том, почему. ,

http://en.wikipedia.org/wiki/Static_cast

http://en.wikipedia.org/wiki/Dynamic_cast

http://en.wikipedia.org/wiki/Reinterpret_cast

JinX
источник
3

Это действительно зависит от того, с каким языком я работаю, так как вы знаете, что они говорят: в Риме говорят по-римски. Поэтому, если я программирую на C, я стараюсь максимально использовать возможности C, но если я программирую на C ++, я продолжаю и максимально использую возможности C ++, даже если некоторым людям не нравится такой подход, потому что говорят, что это делает код «менее переносимым», я говорю, что мне все равно, я на C ++ и программирую на C ++, и мне нужен полностью совместимый с C ++ компилятор для компиляции кода, иначе я бы работал с чем-то другим на первом месте.

Coyote21
источник
Это на самом деле не работает, пытаясь использовать приведения в стиле C ++ в C ;-)
Steve314
3

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

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

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

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

Steve314
источник