Какой идиоматический способ документировать static_cast?

Я это понимаю (MyType)foo, MyType(foo), а также static_cast<MyType>(foo) несколько похожи в том, что первые два становятся последними (РЕДАКТИРОВАТЬ: я был исправлен. Предыдущее предложение не соответствует действительности.) Мой вопрос: какую идиоматическую версию использовать? Является ли контекст соображением?

Поскольку я знаю, что приведение типов в C не является предпочтительным в C++, оно сводится к функциональным приведениям и static_cast.

3 ответа

Решение

Первые два, (MyType)foo а также MyType(foo), имеют такое же значение. Что это означает, зависит от MyType и тип foo, Так, например:

((int)1.0);   // a static_cast
int i = 0;
((char*)&i);  // a reinterpret_cast
const int j = 0;
((int*)&j);   // a const_cast
((char*)&j);  // a combination of a const_cast and a reinterpret_cast

typedef char *CharPtr;
CharPtr(&j);  // a C-style cast, same as ((CharPtr)&j) or ((char*)&j)

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

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

Приведения в функциональном стиле с одним аргументом - в C-стиле. Они четко определены в стандарте и означают одно и то же во всех случаях.

Теперь в некоторых случаях вы можете принять приведение в стиле C, когда оно написано в функциональном синтаксисе, но не в том случае, если оно написано с использованием синтаксиса C. Обычно это происходит, когда типом назначения является класс, и очевидно, какой конструктор будет вызываться. В таком случае, std::vector<int>(0) короче чем static_cast<std::vector<int>>(0)и, как правило, понятнее, поскольку его можно прочитать как вызов конструктора. Но он по-прежнему та же "опасность", что и письмо (std::vector<int>)0, Если бы вы писали каждое преобразование таким образом, то в итоге вы бы случайно удалили const из типа указателя.

Использование явного приведения является идиоматическим в моей книге.

static_cast<MyType>(foo) лучше, чем (MyType)foo потому что это более выразительно и явно. Это особенно полезно во многих случаях, когда (MyType)foo не означает, что вы ожидаете, что это будет означать. Например, в ваших примерах эти случаи могут не сводиться к static_cast вообще, но reinterpret_cast,

В обзоре кода я бы отверг все и все приведения в стиле C к неарифметическим типам.

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

C-стиль бросает сначала попытаться static_castи если это не сработает, делает reinterpret_cast1 Это плохо, потому что операции, предназначенные для простого изменения, могут стать очень странными.

Например, предположим, у вас есть Foo* f и совершенно не связанный класс Bar, Вы можете (Bar*)f и это будет молча переосмыслить *f быть Barвероятно ведет к неопределенному поведению.

static_cast будет работать только в этой ситуации, если Foo а также Bar были родственные типы.

Теперь даже static_cast может быть слишком сильным, поэтому я часто пишу implicit_cast или же non_cast Шаблон, который конвертирует без приведения. Точно так же я пишу as_const это добавляет const вместо того, чтобы требовать const_cast (который может как добавлять, так и удалять constи удаление const гораздо опаснее, чем добавить его).

Несколько досадно, что в C++ нет явного безопасного приведения, и я не знаю, как его написать (тот, который будет выполняться explicit конструкторы, но не будут "сбрасывать" иерархию типов, как static_cast будут).


1 это слишком упрощенное, но достаточно близкое к истине.

Другие вопросы по тегам