66 votes

Utilisation des opérateurs point (".") et flèche ("->") en C et en Objective-C

J'essaie de comprendre les différences d'utilisation et de syntaxe entre le C et l'Objective-C. En particulier, je voudrais savoir comment (et pourquoi) l'utilisation de l'opérateur point et de l'opérateur flèche diffère en C et en Objective-C. En particulier, j'aimerais savoir comment (et pourquoi) l'utilisation de l'opérateur point et de l'opérateur flèche diffère entre le C et l'Objective-C. Voici un exemple simple.

C Code :

// 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

Code 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??

Donc, en voyant comment frac est le même dans les deux programmes (c'est-à-dire qu'il s'agit d'un pointeur vers un objet Fraction ou une structure), pourquoi utilisent-ils une syntaxe différente pour accéder aux propriétés ? En particulier, en C, la fonction numerator est accessible avec frac->numerator mais avec l'Objective-C, on y accède en utilisant l'opérateur point, avec frac.numerator . Puisque frac est un pointeur dans les deux programmes, pourquoi ces expressions sont-elles différentes ? Quelqu'un peut-il m'aider à clarifier ce point ?

87voto

darvids0n Points 7914

frac n'est en fait pas la même dans les deux programmes.

A C Fraction est un struct Il s'agit d'un type de base sans opérateurs surchargés, qui ne peut être construit et détruit que par défaut. Si vous définissez des fonctions ou des champs sur la structure, la façon d'accéder à ces propriétés dans le fichier C est avec le point ( . ). Objective-C conserve cet opérateur lorsque vous utilisez struct s. Pour plus de commodité, vous pouvez effectuer une opération de déréférencement et de pointage en utilisant la flèche ( -> ) (les deux expressions équivalentes que vous mentionnez). Objective-C préserve également cela lors de l'accès à struct s.

Un programme en Objective-C Fraction dans votre exemple, cependant, est probablement (on pourrait le supposer) un pointeur d'au moins type id qui est simplement un nom de classe et un pointeur vers l'instance de cette classe sous le capot. Il est également très probable qu'il s'agisse d'une sous-classe de NSObject o NSProxy . Ces classes Objective-C sont particulières dans la mesure où elles comportent toute une série d'opérations prédéfinies en plus d'une simple classe C (si vous voulez vraiment creuser la question, vous pouvez jeter un coup d'œil à la structure de l'UE). Référence pour l'exécution d'Objective-C ). Il est également important de noter qu'une classe Objective-C est toujours un pointeur .

L'une des opérations les plus fondamentales est objc_msgSend . Lorsque nous opérons sur ces types d'objets, le compilateur Objective-C interprète un point ( . ) ou la syntaxe des crochets ( [object method] ) comme un objc_msgSend l'appel de la méthode. Pour des informations plus détaillées sur ce qui se passe réellement ici, voir cette série d'articles par Bill Bumgarner, un ingénieur d'Apple qui supervise le développement du runtime Obj-C.

La flèche ( -> ) n'est pas vraiment censé être utilisé sur des objets Objective-C. Comme je l'ai dit, les instances de classe Objective-C sont des structures C avec une couche de communication supplémentaire, mais cette couche de communication est essentiellement contournée lorsque vous utilisez la flèche. Par exemple, si vous ouvrez Xcode et tapez [UIApplication sharedApplication]-> et ensuite faire apparaître la liste des méthodes à compléter, vous voyez ceci :

A list of internal ivars on an Obj-C object when using the arrow operator

Ici, vous pouvez voir un groupe de champs normaux auxquels nous accédons généralement avec la syntaxe des crochets (comme [[UIApplication sharedApplication] delegate] ). Ces éléments particuliers sont toutefois les C qui stockent les valeurs de leurs propriétés Objective-C respectives.

Donc, vous pouvez grossièrement penser à ça comme ça :

Opérateur point sur un objet C

  1. (au moment de l'exécution) Valeur de retour du champ

Opérateur de flèche sur un objet C (pointeur)

  1. Pointeur déréférencé
  2. Valeur de retour du champ

Opérateur point/parenthèses sur un objet Objective-C (pointeur)

  1. (au moment de la compilation) Remplacer par un appel à objc_msgSend
  2. (au moment de l'exécution) recherche la définition de la classe Obj-C, lève une exception si quelque chose ne va pas.
  3. Pointeur déréférencé
  4. Valeur de retour du champ

Opérateur de flèche sur un objet Objective-C (pointeur)

  1. (au moment de l'exécution) Pointeur déréférencé
  2. Valeur de retour du champ

Je simplifie certainement à l'extrême, mais pour résumer : les opérateurs flèches semblent faire la même chose dans les deux cas, mais l'opérateur point a une signification supplémentaire/différente en Objective-C.

9voto

justin Points 72871

La notation par points est un choix de conception. Comme nous avons toujours affaire à des pointeurs vers des instances d'ObjC, je suppose que les concepteurs voulaient quelque chose de familier, qui ne casserait pas non plus les programmes existants. Elle a été introduite dans ObjC 2, il y a quelques années seulement. Avant cela, vous deviez toujours utiliser des parenthèses pour la messagerie.

La notation par points fait cependant une différence : il ne s'agit pas d'un accès direct, mais d'une message .

C'est-à-dire :

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;

Vous pouvez toujours écrire obj->ivar pour accéder à un pointeur sur les membres de l'objet (s'ils sont visibles).

5voto

KomodoDave Points 2605

Dans votre premier exemple, Fraction est un struct. Dans votre deuxième exemple, Fraction est une classe Objective-C (et dans iOS, elle serait probablement une sous-classe de NSObject ).

C++ ne permet pas surcharge de operator . . Par conséquent, sans information supplémentaire, vous pouvez déduire que la notation du point que vous voyez est une construction supplémentaire du langage intégrée à l'Objective-C, plutôt qu'un opérateur défini ou surchargé en C/C++.

Il se trouve que la notation par points est simplement une caractéristique de conception que les implémenteurs ont choisie comme raccourci pour l'accès aux propriétés, tout à fait équivalent au getter entre crochets :

myObjCVar.prop == [myObjCVar prop];

2voto

Chuck Points 138930

L'opérateur point sur les objets est une syntaxe spéciale pour accéder aux propriétés des objets. Il appelle le getter ou le setter de la propriété en coulisse. Ainsi, par exemple [@"hello" length] y @"hello".length sont équivalents*. Pour tous les autres types, le point est le même que le point C, et la flèche est toujours la même.

* Note : La méthode de l'accesseur ne portera pas toujours le même nom que la propriété. S'il s'agit d'une propriété déclarée et que la déclaration désigne une méthode getter ou setter spéciale, celle-ci sera utilisée à la place.

1voto

5StringRyan Points 1838

La notation par points et par flèches est la même en C et en Objective-C (strict superset of ). Je pense que la différence fondamentale qui doit être distinguée est la différence entre un struct et un objet Objective-C.

La notation point utilisée pour les objets en Objective-C est utilisée pour les propriétés, introduite en Objective-C 2.0. En revanche, pour les structs, les notations -> et point sont identiques en Objective-C et en C.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X