Зачем использовать static_cast < int > (x) вместо (int) x?

Интересно, что это не влияет на словарь или задание понятий.

>>> [x for x in range(1, 10)]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x
9
>>> {x for x in range(1, 5)}
set([1, 2, 3, 4])
>>> x
9
>>> {x:x for x in range(1, 100)}
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15, 16: 16, 17: 17, 18: 18, 19: 19, 20: 20, 21: 21, 22: 22, 23: 23, 24: 24, 25: 25, 26: 26, 27: 27, 28: 28, 29: 29, 30: 30, 31: 31, 32: 32, 33: 33, 34: 34, 35: 35, 36: 36, 37: 37, 38: 38, 39: 39, 40: 40, 41: 41, 42: 42, 43: 43, 44: 44, 45: 45, 46: 46, 47: 47, 48: 48, 49: 49, 50: 50, 51: 51, 52: 52, 53: 53, 54: 54, 55: 55, 56: 56, 57: 57, 58: 58, 59: 59, 60: 60, 61: 61, 62: 62, 63: 63, 64: 64, 65: 65, 66: 66, 67: 67, 68: 68, 69: 69, 70: 70, 71: 71, 72: 72, 73: 73, 74: 74, 75: 75, 76: 76, 77: 77, 78: 78, 79: 79, 80: 80, 81: 81, 82: 82, 83: 83, 84: 84, 85: 85, 86: 86, 87: 87, 88: 88, 89: 89, 90: 90, 91: 91, 92: 92, 93: 93, 94: 94, 95: 95, 96: 96, 97: 97, 98: 98, 99: 99}
>>> x
9

Однако он был исправлен в 3, как указано выше.

602
задан Rakete1111 14 March 2017 в 18:31
поделиться

8 ответов

Главная причина состоит в том, что классические броски C не делают различия между тем, что мы называем static_cast<>(), reinterpret_cast<>(), const_cast<>(), и dynamic_cast<>(). Эти четыре вещи полностью отличаются.

А static_cast<>() обычно безопасен. Существует допустимое преобразование на языке или соответствующий конструктор, который позволяет. Единственное время это немного опасно, - когда Вы разрушаете к наследованному классу; необходимо удостовериться, что объект является на самом деле потомком, что Вы утверждаете, что это средствами, внешними на язык (как флаг в объекте). dynamic_cast<>() безопасно, пока результат проверяется (указатель), или возможное исключение принято во внимание (ссылка).

А reinterpret_cast<>() (или const_cast<>()), с другой стороны, всегда опасен. Вы говорите компилятор: "доверяйте мне: Я знаю, что это не похоже foo (это смотрит, как будто это не изменяемо), но это".

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

Позволяют нам принять их:

class CDerivedClass : public CMyBase {...};
class CMyOtherStuff {...} ;

CMyBase  *pSomething; // filled somewhere

Теперь, эти два компилируются тот же путь:

CDerivedClass *pMyObject;
pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked

pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<>
                                     // Safe; as long as we checked
                                     // but harder to read

Однако позволяют нам видеть этот почти идентичный код:

CMyOtherStuff *pOther;
pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert

pOther = (CMyOtherStuff*)(pSomething);            // No compiler error.
                                                  // Same as reinterpret_cast<>
                                                  // and it's wrong!!!

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

вторая проблема состоит в том, что броски C-стиля слишком трудны для определения местоположения. В сложных выражениях может быть очень трудно видеть броски C-стиля. Фактически невозможно записать автоматизированный инструмент, который должен определить местоположение бросков C-стиля (например, средство поиска) без полноценного фронтенда компилятора C++. С другой стороны, легко искать "static_cast<"; или "reinterpret_cast<";.

pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
      // No compiler error.
      // but the presence of a reinterpret_cast<> is 
      // like a Siren with Red Flashing Lights in your code.
      // The mere typing of it should cause you to feel VERY uncomfortable.

, Который означает, что, мало того, что броски C-стиля более опасны, но и намного более трудно найти, что они все удостоверяются, что они корректны.

589
ответ дан Jarvis 14 March 2017 в 18:31
поделиться

Одна прагматическая подсказка: можно искать легко static_cast ключевое слово в исходном коде, если Вы планируете убрать проект.

109
ответ дан Karl 14 March 2017 в 18:31
поделиться

static_cast средства, что Вы не можете случайно const_cast или reinterpret_cast, который является хорошей вещью.

24
ответ дан cbuchart 14 March 2017 в 18:31
поделиться

static_cast, кроме управления указателями на классы, может также использоваться, чтобы выполнить преобразования, явно определенные в классах, а также выполнить стандартные преобразования между фундаментальными типами:

double d = 3.14159265;
int    i = static_cast<int>(d);
4
ответ дан prakash 14 March 2017 в 18:31
поделиться

Это о том, сколько безопасности типов Вы хотите наложить.

, Когда Вы пишете (bar) foo (который эквивалентен reinterpret_cast<bar> foo, если Вы не обеспечили оператор преобразования типов) Вы говорите компилятору игнорировать безопасность типов, и просто делать, как это сказано.

, Когда Вы пишете static_cast<bar> foo, Вы просите, чтобы компилятор, по крайней мере, проверил, что преобразование типов имеет смысл и, для целочисленных типов, вставлять некоторый код преобразования.

<час>

РЕДАКТИРОВАНИЕ 26.02.2014

я записал этот ответ больше чем 5 лет назад, и я понял его превратно. (См. комментарии.), Но это все еще получает upvotes!

7
ответ дан Pitarou 14 March 2017 в 18:31
поделиться
  1. Позволяет броскам быть найденными легко в Вашем коде с помощью grep или подобных инструментах.
  2. Делает его явным, какой брошенный Вы делаете и вовлекаете справку компилятора в осуществление его. Если Вы только хотите выбросить мыс константы, то можно использовать const_cast, который не позволит Вам делать другие типы преобразований.
  3. Броски по сути ужасны - Вы как программист взяли верх, как компилятор обычно рассматривал бы Ваш код. Вы говорите компилятору, "Я знаю лучше, чем Вы". При этом это имеет смысл, который выполнение броска должно быть умеренно болезненной вещью сделать, и что они должны перетерпеть в Вашем коде, так как они - вероятный источник проблем.

См. Эффективный C++ Введение

7
ответ дан JohnMcG 14 March 2017 в 18:31
поделиться

C броски Стиля легки отсутствовать в блоке кода. Броски стиля C++ не являются только лучшей практикой; они предлагают намного большую степень гибкости.

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

static_cast предлагает хорошее преобразование для числовых типов, например, от как перечисления к ints или ints к плаваниям или любым типам данных, Вы уверены в типе. Это не выполняет проверок времени выполнения.

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

существует несколько других, но это основные, с которыми Вы столкнетесь.

4
ответ дан Konrad 14 March 2017 в 18:31
поделиться

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

На поверхности static_cast и броски стиля C появляются к тому же самому, например, при кастинге одного значения другому:

int i;
double d = (double)i;                  //C-style cast
double d2 = static_cast<double>( i );  //C++ cast

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

class A {};
class B : public A {};

A* a = new B;
B* b = (B*)a;                                  //(1) what is this supposed to do?

char* c = (char*)new int( 5 );                 //(2) that weird?
char* c1 = static_cast<char*>( new int( 5 ) ); //(3) compile time error

В этом примере (1) возможно, хорошо, потому что объект, на который указывает A, является действительно экземпляром B. Но что, если Вы не знаете в той точке в коде, что на самом деле указывает на? (2) возможно, совершенно законный (Вы только хотите посмотреть на один байт целого числа), но это могла также быть ошибка, в этом случае ошибка, будет хорош, как (3). Операторы кастинга C++ предназначаются для представления этих проблем в коде путем обеспечения времени компиляции или ошибок времени выполнения, если это возможно.

Так, для строгого "значения, бросая" можно использовать static_cast. Если Вы хотите полиморфный кастинг во время выполнения использования указателей dynamic_cast. Если Вы действительно хотите забыть о типах, можно использовать reintrepret_cast. И просто бросить константу из окна существует const_cast.

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

27
ответ дан Dusty Campbell 14 March 2017 в 18:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: