В чем разница между static_cast <> и кастом в стиле C?


Ответы:


217

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

Кроме того, можно легко найти приведения в стиле c ++, в то время как действительно сложно найти приведения в стиле c.

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

При написании C ++ я почти всегда использовал C ++ поверх стиля C.


67
Единственное приведение, которое может потерпеть неудачу во время выполнения, это dynamic_casts.
Р. Мартиньо Фернандес

12
C ++ reinterpret_cast <T> (U) может завершиться с ошибкой во время выполнения почти так же, как и приведения типов в стиле C, и все они сильно отличаются от того, как dynamic_cast <T> (U) дает сбой.
Кристофер Смит

20
Normal1 обычное приведение C (int)somethingне может завершиться неудачей - либо вы приведете к типу int, либо к ошибке компилятора.
Томаш Зато - Восстановить Монику

2
Можете ли вы объяснить, почему приведения C ++ можно искать легче, чем приведения C?
Минь Чен

3
@MinhTran Для стиля C ++ вы можете искать ключевое слово «cast» через ваши исходные файлы. Но хотите ли вы сделать с бросками в стиле c?
Хуанцзунхао

176

Короче говоря :

  1. static_cast<>() дает вам возможность проверки времени компиляции, а C-Style - нет.
  2. static_cast<>() более читабелен и может быть легко обнаружен в любом месте исходного кода C ++, приведение C_Style is'nt.
  3. Намерения передаются намного лучше, используя приведения C ++.

Более объяснение :

Статическое приведение выполняет преобразования между совместимыми типами . Это похоже на приведение в стиле C, но является более ограничительным. Например, приведение в стиле C позволит целочисленный указатель указывать на символ.

char c = 10;       // 1 byte
int *p = (int*)&c; // 4 bytes

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

*p = 5; // run-time error: stack corruption

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

int *q = static_cast<int*>(&c); // compile-time error

Вы также можете проверить эту страницу с более подробным объяснением приведений C ++: Нажмите здесь


17
Я думаю, что вместо «4-байтовый указатель» вы имели в виду «указатель на 4-байтовый тип данных»
iheanyi

но это позволяет int q = static_cast <int> (c);
TonyParker

3
@TonyParker Это потому, что в этой строке нет ничего плохого.
Брэден Бест

15

Смотрите Сравнение операторов приведения C ++ .

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

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

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


14
struct A {};
struct B : A {};
struct C {}; 

int main()
{
    A* a = new A;    

    int i = 10;

    a = (A*) (&i); // NO ERROR! FAIL!

    //a = static_cast<A*>(&i); ERROR! SMART!

    A* b = new B;

    B* b2 = static_cast<B*>(b); // NO ERROR! SMART!

    C* c = (C*)(b); // NO ERROR! FAIL!

    //C* c = static_cast<C*>(b); ERROR! SMART!
}

5
Не могли бы вы более подробно изложить свой ответ, добавив чуть больше описания предлагаемого вами решения?
abarisone

1
Я думаю, что ответ показывает, что «static_casts» проверяет преобразования типов, чтобы убедиться, что они находятся на допустимых путях в графе иерархии. В этом конкретном примере приведение от A * к B * или от B * к A * разрешено, потому что A и B образуют путь в иерархическом графе. C * не находится на пути, поэтому static_cast выдаст ошибку во время компиляции. Примечание. Может быть, стоит отметить, что приведение от A * к B * может привести к NULL с dynamic_cast во время выполнения в зависимости от истинного базового объекта.
Томми Чен

7

Отличный пост, объясняющий различные приведения в C / C ++ и что на самом деле делает приведение в стиле C: https://anteru.net/blog/2007/12/18/200/index.html

Приведение в стиле C с использованием синтаксиса переменной (type). Худшее из когда-либо изобретенных. Это попытается выполнить следующие приведения в указанном порядке: (см. Также C ++ Standard, 5.4 expr.cast, параграф 5)

  1. const_cast
  2. static_cast
  3. static_cast с последующим const_cast
  4. reinterpret_cast
  5. reinterpret_cast следует за const_cast

5

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

static_cast используется для преобразования из указателя в базовый класс в указатель на производный класс или между нативными типами, такими как enum в int или float в int.

Пользователь static_castдолжен убедиться, что преобразование безопасно.

Приведение в стиле C не выполняет никакой проверки ни во время компиляции, ни во время выполнения.


3

Поскольку существует много разных типов приведения, каждый из которых имеет разную семантику, static_cast <> позволяет вам сказать: «Я делаю законное преобразование из одного типа в другой», например, из int в double. Простой C-стиль может означать многое. Вы кастинг вверх / вниз? Вы переосмысливаете указатель?

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.