кастинг сравнения между Objective C и C++

Хорошо, таким образом, это могло бы быть определенным академическим вопросом. Кто-то может сказать мне, если/как операторы кастинга C++ могли бы перевести в Objective C... или как/почему они не необходимы?

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

Я использовал Objective C в течение года или два теперь и чувствую себя справедливо комфортно с ним. (Главным образом человек C до тех пор). Я пытаюсь понять, почему C++, кажется, имеет всю эту сложность. Или, другими словами, что Objective C пропускает это, это, кажется, не имеет (или потребность?) это много типов кастинга?

5
задан Danny Sung 30 June 2010 в 07:18
поделиться

4 ответа

Смотрите этот ответ на вопрос Когда следует использовать static_cast, dynamic_cast и reinterpret_cast? о значении каждого вида кастов.

чего не хватает Objective-C, что не имеет (или не нуждается?) в таком количестве типов приведения?

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

  • В Objective-C нет const объектов (const NSObject*), а другие const параметры не так акцентированы, в отличие от C++, поэтому const_cast бесполезен.

  • Экземпляры Objective-C всегда используют динамическую типизацию, поэтому dynamic_cast не нужен. (Проверка типов в ObjC обычно выполняется с помощью -isKindOfClass:).

  • static_cast и reinterpret_cast одинаковы в C, но не так в C++. Поскольку C++ поддерживает множественное наследование (отсутствующее в ObjC), приведение указателя не так просто, как no-op:

    #include 
    
    struct A {
     int x;
     A() : x(12) {}
    };
    struct B {
     int y;
     B() : y(33) {}
     int get() const { return y; }
    };
    struct C : A, B {
     int z;
     C() : A(), B(), z(41) {}
    };
    
    int main () {
     C* c = new C;
     printf("%d\n", c->get()); // 33
     printf("%d\n", static_cast(c)->get()); // 33
     printf("%d\n", reinterpret_cast(c)->get()); // 12
    }
    
9
ответ дан 18 December 2019 в 16:35
поделиться

Дело в том, что существует несколько совершенно разных категорий приведений с разным намерением, и желательно иметь возможность явно указывать это намерение, чтобы вы случайно не сделали неправильных вещей. . Например, вы можете преобразовать const int * в const char * для работы с необработанными байтами и непреднамеренно также отбросить const . Следовательно, в C ++ изменение указателя с одного несвязанного типа на другой выполняется с помощью reinterpret_cast , тогда как отбрасывание const можно выполнить только с помощью const_cast . Если вы попробуете const void * p; reinterpret_cast (p) , вы получите сообщение об ошибке.

dynamic_cast необходим для надежного понижающего преобразования (с проверкой во время выполнения), а также для перекрестного преобразования (т.е. с указанием типа Base1 * на объект фактического типа Производный , который наследуется от Base1 * и Base2 * , чтобы иметь возможность напрямую приводить к Base2 * ; и то же самое для ссылок - это особенно полезно для "интерфейсов").

static_cast и все остальное - преобразование значений (int <-> float и т. Д.), Преобразование указателей / ссылок на объекты с повышением частоты и неконтролируемое понижающее преобразование.Он также используется наиболее часто, хотя некоторые руководства по стилю призывают использовать dynamic_cast для всех приведений указателей / ссылок на объект, насколько это возможно.

В общем, логическое объяснение выглядит следующим образом: две наиболее опасные операции (приведение к типу указателя на несвязанный и отбрасывание константности) обеспечиваются собственными выделенными операторами приведения, чтобы предотвратить любую возможность их случайного возникновения. После этого предоставляется новый оператор для случаев, когда приведение требует поиска во время выполнения. Наконец, предоставляется еще один новый оператор для покрытия оставшейся территории. Старый «универсальный» оператор приведения в стиле C устарел.

Теперь о том, почему Obj-C не «нужны» они. Возможно, он действительно мог использовать разницу между const_cast , reinterpret_cast и static_cast - но они, по-видимому, не добавляли достаточной ценности для расширения ядра C язык. Ему не требуется dynamic_cast , потому что он не имеет множественного наследования (протоколы несколько отличаются), а проверка типов вместо этого выполняется с помощью метода isa .

1
ответ дан 18 December 2019 в 16:35
поделиться

Прочтите статью на CPlusPlus.com , в которой подробно описаны различные методы приведения типов.

  1. reinterpret_cast преобразует любой тип указателя в любой другой тип указателя, даже несвязанных классов. Результатом операции является простая двоичная копия значения одного указателя на другой. Разрешены все преобразования указателей: ни указанное содержимое, ни сам тип указателя не проверяются.
  2. static_cast может выполнять преобразования между указателями на связанные классы не только из производного класса в его базовый, но также из базового класса в его производный. Это гарантирует, что по крайней мере классы совместимы, если соответствующий объект преобразован, но во время выполнения не выполняется проверка безопасности, чтобы проверить, действительно ли преобразованный объект является полным объектом целевого типа.
  3. dynamic_cast может использоваться только с указателями и ссылками на объекты. Его цель - гарантировать, что результатом преобразования типа является действительный полный объект запрошенного класса.
  4. const_cast - это тип преобразования, который управляет константностью объекта, который должен быть установлен или удален. Например, чтобы передать аргумент const функции, которая ожидает непостоянный параметр

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

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

1
ответ дан 18 December 2019 в 16:35
поделиться

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

Тот, который сильно отличается от Objective C, - это dynamic_cast , который выполняет дополнительную проверку времени выполнения, чтобы убедиться, что объект имеет желаемый тип перед преобразованием к нему, и возвращает 0 или генерирует исключение, если он не существует. Это похоже на вызов isKindOfClass в NSObject перед преобразованием Objective C, и в мире C ++ очень полезно для понижения. Однако обратите внимание, что из-за динамической диспетчеризации метода в Objective C вам не нужно понижать значение объекта, прежде чем вы сможете отправить ему конкретные сообщения для его типа, поэтому роль понижающего преобразования меньше, чем в мире C ++.

1
ответ дан 18 December 2019 в 16:35
поделиться
Другие вопросы по тегам:

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