2009-12-28 8 views
1

quelqu'un peut-il me dire quelle est la différence entre (*ptr).field et ptr->field? Je sais qu'il se connecte en quelque sorte à la liaison statique et dynamique, mais je ne sais pas ce que c'est. quelqu'un peut-il me dire le differnet et me donner un exemple?Différences d'accès des membres

modifier: si j'ai ce code:

Point p;  //point is a class that derive from class shape 
Shape *s=&p; 
       //there is a diffrence if i write: 

(*s).print(); //print is virtual func 
s->print(); // the answers will not be the same, why? 

TNX!

+0

Voulez-vous dire '(* ptr) .field' ou' * ptr.field'? Si vous vouliez vraiment dire '* ptr.champ », alors ces deux formes n'ont rien en commun, ce qui rend la question pratiquement dénuée de sens. – AnT

+0

je voulais dire (* ptr) .field – aharon

+0

De votre vérification: La réponse sera la même. Voir ci-dessous. –

Répondre

4

il n'a rien à voir avec la liaison statique ou dynamique les deux expressions renvoie la valeur de ptr.field

la ptr-> forme de champ est une syntaxe abrégée pour accéder à un membre directement à partir d'un pointeur

MISE à JOUR: il me vint que votre intention initiale était pas l'enchaînement mais liant si cela était en effet ce que vous visiez à alors il est liaison statique et dynamique obligatoire qui ont une certaine relation avec l'opérateur ->see here

+1

Oui, mais abrégé pour (* ptr) .fld, pas pour * ptr.field. – ChrisInEdmonton

+1

Il est important de noter que ceux-ci ne sont PAS nécessairement équivalents, en raison de la possibilité de surcharger l'opérateur * et l'opérateur-> en C++! – HostileFork

+2

@Hostile Fork: C'est pourquoi, dans certains magasins, les sessions de révision de code C++ devraient inclure des machines de thérapie par électrochocs. –

2

de liaison statique est le résultat de la copie de linker toutes les routines de bibliothèque utilisées dans le programme dans l'image exécutable. Cela peut nécessiter plus d'espace disque et de mémoire que la liaison dynamique, mais il est à la fois plus rapide et plus portable, car il ne nécessite pas la présence de la bibliothèque sur le système où il est exécuté.

La liaison dynamique est accomplie en plaçant le nom d'une bibliothèque partageable dans l'image exécutable. La liaison réelle avec les routines de bibliothèque ne se produit pas jusqu'à ce que l'image soit exécutée, lorsque l'exécutable et la bibliothèque sont placés en mémoire. Un avantage de la liaison dynamique est que plusieurs programmes peuvent partager une seule copie de la bibliothèque.

Mais il n'est pas lié à l'indirection de pointeur que vous avez mentionnée - en fait, ces deux expressions sont identiques.

+1

Pas tout à fait. Le champ ptr-> est identique à (* ptr) .field, pas à * ptr.field. – ChrisInEdmonton

0

Ils sont identiques.
*ptr.field déréférences la variable ptr puis renvoie la valeur du membre field.

L'opérateur -> est une notation abrégée pour ce qui précède.

+2

En fait, '* ptr.field' est évalué comme' * (ptr.field) ', pas' (* ptr) .field'. –

1

Cela n'a rien à voir avec la liaison.

ptr->fld 

est simplement un raccourci pour

(*ptr).fld 

Il est pur sucre syntaxique;)

+0

En particulier, voir le § 5.2.5.3 de la norme C++. – outis

+1

§ 5.2.5 3 Si E1 a le type "pointeur vers classX," alors l'expression E1-> E2 est convertie en forme équivalente (* (E1)). E2; le reste de 5.2.5 ne traitera que la première option (point). – outis

+0

@outis: La partie que vous avez citée décrit le comportement de * l'opérateur intégré * -> '. N'oubliez pas que '->' en C++ ne fait pas nécessairement référence à l'opérateur intégré. Il peut également être surchargé par l'utilisateur. L'OP n'a pas dit que 'ptr' était de type pointeur brut. – AnT

2

Je suppose que vous vouliez dire par *ptr.field(*ptr).field.

Dans la mesure où seuls les opérateurs intégrés sont pris en compte, il n'y a pas de différence entre les deux. Et non, cela n'a rien à voir avec un lien "statique" ou "dynamique", quoi que ce soit impliqué par ces termes.

La seule différence de potentiel entre les deux est que dans ptr->field variante -> est un opérateur surchargeable en C++, tandis que dans la variante (*ptr).field seulement * est surchargeable, tandis que . est pas.

De plus, certaines différences entre ces deux méthodes d'accès aux membres existaient dans des versions très archaïques du langage C (CRM C), mais je doute que quiconque s'en soucie aujourd'hui.

1

Tant que ptr est un pointeur, les deux sont équivalents une fois correctement entre parenthèses (comme d'autres l'ont dit). Si ptr est un objet, plutôt qu'un pointeur, ils peuvent être différents selon les définitions pour operator* et operator-> (le cas échéant) de la classe ou des ancêtres de l'objet.

+0

ok, si j'ai ce code: Point p; // point est une classe qui dérive de la forme de la classe Shape * s = & p; il y a une différence si j'écris (* s) .print(); // print est la fonction virtuelle à s-> print(); Les réponses ne seront pas les mêmes, pourquoi? – aharon

7

Cela n'a rien à voir avec la liaison statique ou dynamique.

Voir C++'s operator precedence. Le . a une priorité inférieure à *, donc il y a en fait une assez grande différence entre *ptr.fld et ptr->fld. Par exemple, le code suivant montre:

#include <iostream> 

struct foo { 
    int f; 
}; 

int main() { 
    struct foo *p = new struct foo; 
    p->f = 42; 
    std::cout << p->f << std::endl; 
    std::cout << (*p).f << std::endl; 
    // The following will not compile 
    // std::cout << *p.f << std::endl; 
} 

Comme John Knoeller souligne, ptr->fld est le sucre syntaxique pour (*(ptr)).fld, mais n'est pas la même chose que *ptr.fld, qui fait évaluer à *(ptr.fld), probablement pas ce que vous voulez.

Vous utiliseriez ptr->fld lorsque vous avez un pointeur vers une structure et souhaitez accéder à un champ qui y est contenu. (*(ptr)).fld signifie la même chose mais n'est pas aussi bien rangé. Vous utiliseriez *strct.fld lorsque vous avez une structure, pas un pointeur sur une structure, qui contient un champ (fld) qui est un pointeur que vous souhaitez déréférencer. Le cas de ptr->fld est illustré ci-dessus. Le cas de *strct.fld pourrait être utilisé avec la structure suivante:

struct foo { 
    int *fld; 
} 

struct foo f; 
f.fld = new int; 
*f.fld = 42; 
+0

Comme indiqué par outis, ptr-> field est en fait du sucre syntatique pour (* (ptr)). Field, pas pour (* ptr) .field. Oups. Fixé. – ChrisInEdmonton

+0

Puisque 'ptr' est un identifiant,' (* ptr) .field' est correct. Pourtant, il est bon de souligner le cas général. – outis

+0

L'OP a confirmé qu'il voulait vraiment dire '(* ptr) .field'. J'ai édité la question. – AnT

1

Le formulaire -> est juste un raccourci pour de-refrencing le pointeur et l'accès au membre.

(*ptr).field; 
// Equiv to 
ptr->field; 

Une bonne raison d'utiliser -> est que lorsque vous suivez une chaîne:

int x = (*(*(*(*ptr).field1).field2).field3).field4; 
// Equiv to 
int y = ptr->field1->field2->field3->field4; 

Le second devient beaucoup plus lisible.

Comme pour la deuxième partie de votre question.
Je trouve vraiment facile de trouver un exemple.

#include <iostream> 

class Shape 
{ 
    public: virtual ~Shape()  {} 
       virtual void Print() {std::cout << "Shape\n";} 
}; 
class Point: public Shape 
{ 
    public: virtual void Print() {std::cout << "Point\n";} 
}; 

int main() 
{ 
    Point p; 
    Shape* s = &p; 

    s->Print(); 
    (*s).Print(); 
} 

> vi x.cpp 
> g++ x.cpp 
> ./a.exe 
Point 
Point 

Comme vous pouvez le voir le résultat est le même dans les deux situations.

Lorsque vous appelez une méthode via un pointeur ou une référence, le mécanisme d'appel virtuel est appelé. L'opérateur star (AKA derefence operator) renvoie une référence à un objet (il ne dé-référence pas réellement l'objet). Donc, quand il est utilisé pour appeler une méthode, le mécanisme d'appel virtuel sera appelé et la version la plus dérivée de la méthode appelée.

+0

ok, les chars, bien que mon DR. dit il y a un peu différent, mais je ne me souviens pas de quoi ... – aharon

+0

Il n'y a pas de différence entre (* ptr) -> f1 et ptr-> f1. C'est défini par la norme. Si nous passons aux fonctions virtuelles. Il y a des situations où le mécanisme d'appel de la vertu ne sera pas utilisé, mais ce n'est pas le cas. –

+0

alors quel est le cas que le mécanisme d'appel de la vertu ne sera pas utilisé? – aharon