Оператор Dot (“.”) И стрелка (“->”) используют в C против Objective-C

Я пытаюсь склонить голову к некоторым различиям в использовании и синтаксисе в C против Objective-C. В частности, я хочу знать, как (и почему) использование отличается для оператора точки и оператора стрелки в C по сравнению с Objective-C. Вот простой пример.

C Код:

// declare a pointer to a Fraction struct Fraction *frac; ... // reference an 'instance' variable int n = (*frac).numerator; // these two expressions int n = frac->numerator; // are equivalent 

Код Objective-C:

 // declare a pointer to a Fraction Fraction *frac = [[Fraction alloc] init]; ... // reference an instance variable int n = frac.numerator; // why isn't this (*frac).numerator or frac->numerator?? 

Таким образом, видя, как в обеих программах один и тот же файл (то есть он является указателем на объект или структуру фракции), почему они используют другой синтаксис при доступе к свойствам? В частности, в C свойство numerator получает доступ с помощью frac->numerator , но с Objective-C он обращается к оператору точек с помощью frac.numerator . Поскольку frac является указателем в обеих программах, почему эти выражения отличаются друг от друга? Может ли кто-нибудь помочь прояснить это для меня?

frac на самом деле не одинакова в обеих программах.

AC Fraction – это struct , которая является базовым типом без перегруженных операторов и действительно может быть сконструирована и разрушена по умолчанию. Если вы определяете функции или поля в структуре, способ доступа к этим свойствам в C является оператором точки ( . ). Objective-C поддерживает этот оператор, когда вы используете struct s. Для удобства вы можете выполнить операцию разыменования и точки с помощью оператора стрелки ( -> ) (упомянутые два эквивалентных выражения). Objective-C также сохраняет это при доступе к struct s.

Однако в вашем примере Fraction Objective-C, возможно, (предположительно) указала хотя бы id типа, который является просто именем classа и указателем на экземпляр этого classа под капотом. Он также, скорее всего, будет подclassом NSProxy или NSProxy . Эти classы Objective-C отличаются тем, что у них есть целый уровень предопределенных операций поверх всего C структуры (если вы действительно хотите в нее вникнуть, тогда вы можете взглянуть на ссылку Objective-C Runtime Reference ). Также важно отметить, что Objective-C-class всегда является указателем .

Одной из основных операций является objc_msgSend . Когда мы работаем над этими типами объектов, компилятор Objective-C интерпретирует оператор точки ( . ) Или синтаксис квадратной скобки ( [object method] ) как objc_msgSend метода objc_msgSend . Более подробную информацию о том, что на самом деле происходит здесь, см. В этой серии статей Билла Бумгарнера, инженера Apple, который курирует разработку среды выполнения Obj-C.

Оператор стрелки ( -> ) на самом деле не должен использоваться для объектов Objective-C. Как я уже сказал, экземпляры classа Objective-C представляют собой C-структуру с добавленным дополнительным слоем связи, но этот уровень связи существенно обойден, когда вы используете стрелку. Например, если вы откроете Xcode и введите в [UIApplication sharedApplication]-> а затем перечислите список завершения метода, вы увидите следующее:

Список внутренних иваров объекта Obj-C при использовании оператора стрелки

Здесь вы можете увидеть кучу нормальных полей, к которым мы обычно обращаемся с синтаксисом с квадратной скобкой (например, [[UIApplication sharedApplication] delegate] ). Однако эти конкретные элементы являются полями C которые сохраняют значения соответствующих свойств Objective-C.

Итак, вы можете примерно подумать об этом так:

Оператор Dot на объекте C

  1. (во время выполнения) Возвращаемое значение поля

Оператор стрелки на объекте C (указатель)

  1. Указатель разыменования
  2. Возвращаемое значение поля

Оператор точки / квадратные скобки объекта Objective-C (указатель)

  1. (во время компиляции) Заменить на вызов objc_msgSend
  2. (во время выполнения) Посмотрите определение classа Obj-C, исключите исключение, если что-то пошло не так
  3. Указатель разыменования
  4. Возвращаемое значение поля

Оператор стрелки объекта Objective-C (указатель)

  1. (во время выполнения) Указатель разыменования
  2. Возвращаемое значение поля

Теперь я определенно упрощаю здесь, но резюмирую: операторы стрелок, похоже, делают в обоих случаях одно и то же, но оператор точки имеет дополнительное / различное значение в Objective-C.

Точечная обозначение – это выбор дизайна. Поскольку мы всегда имеем дело с указателями на экземпляры objc, я бы предположил, что дизайнеры хотели что-то знакомое, что также не нарушало бы существующие программы. Он был введен в ObjC 2 – всего несколько лет назад. До этого вам всегда приходилось использовать скобки для обмена сообщениями.

Точечная нотация имеет значение, хотя – это не прямой доступ, а сообщение .

То есть:

 obj.property = val; // is the same as: [obj setProperty:val]; // and not: obj->property = val; val = obj.property; // is the same as: val = [obj property]; // and not: val = obj->property; 

Вы все равно можете написать obj->ivar для доступа к указателю на элементы объекта (если видимо).

В вашем первом примере Fraction является структурой. Во втором примере Fraction является classом Objective-C (а в iOS, вероятно, будет подclass NSObject ).

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

Так как это происходит, точечное обозначение представляет собой просто конструктивную особенность, которую разработчики выбрали как стенографию для доступа к свойствам, полностью эквивалентную элементу с квадратной скобкой:

 myObjCVar.prop == [myObjCVar prop]; 

Точечный оператор на объектах является специальным синтаксисом для доступа к свойствам объектов. Он вызывает геттер или сеттер объекта за кулисами. Так, например, [@"hello" length] и @"hello".length эквивалентны *. Для всех остальных типов точка совпадает с точкой C, а стрелка всегда одна и та же.

* Примечание. Метод доступа не всегда будет называться так же, как и свойство. Если это объявленное свойство, и объявление обозначает специальный метод getter или setter, тот будет использоваться вместо этого.

Точечные и стрелочные обозначения одинаково одинаковы для C, как в Objective-C (строгий суперсет). Я думаю, что принципиальное отличие, которое нужно различить, – это различие между структурой и объектом Objective-C.

Точечная нотация, используемая для объектов Objective-C, используется для свойств, которые были введены в Objective-C 2.0. Тем не менее, с помощью структур, -> и точечные обозначения между Objective-C и C одинаковы.

  • Является ли sizeof (некоторый указатель) всегда равным четырем?
  • Как избежать утечек памяти при использовании вектора указателей на динамически выделенные объекты в C ++?
  • как отображать изображения, сохраненные в папке sdcard в android
  • Как связаны iteratorы и указатели?
  • Автоматическое открытие InfoWindow при добавлении маркера Google Maps v2 Android
  • Каковы операторы Pointer-to-Member -> * и. * В C ++?
  • Как использовать iterator?
  • Является ли указатель «один-на-конец» типа не-массива допустимым понятием в C ++?
  • Как я могу индексировать массив MATLAB, возвращаемый функцией, не назначая сначала локальную переменную?
  • выделить матрицу в C
  • Давайте будем гением компьютера.