2010-05-04 5 views
3

En Penser en C++ par Bruce Eckel, il est un exemple donné en ce qui concerne les fonctions d'ami commedéclaration d'ami en C++

// Declaration (incomplete type specification): 
struct X; 
struct Y { 
void f(X*); 
}; 
struct X { // Definition 
private: 
int i; 
public: 
friend void Y::f(X*); // Struct member friend 
}; 
void Y::f(X* x) { 
x->i = 47; 
} 

Maintenant, il a expliqué ceci:

Notez que Y :: f (X *) prend l'adresse d'un objet X . Ceci est critique car le compilateur sait toujours comment passer une adresse qui est de taille fixe quel que soit l'objet étant passé, même s'il n'a pas d'informations complètes sur la taille du type. Si vous essayez de passer l'objet entier, cependant, le compilateur doit voir la définition de la structure entière de X, connaître la taille et comment le passer, avant qu'il ne vous permet de déclarer une fonction comme Y :: g (X).

Mais quand j'ai essayé

void f(X); 

comme déclaration Y struct, il montre aucune erreur. S'il vous plaît expliquer pourquoi?

Répondre

1

Les types de paramètre pour la fonction déclarations peuvent être incomplets.

Pour les données des déclarations de membres et toutes définitions cependant, le type doit être complète:

struct A; 
struct B { 
    void f(A); // declaration, fine 
    void g(A) {} // error 
    A a;   // error 
}; 
0

Les problèmes est lorsque vous modifiez la déclaration struct X.

Ainsi, à l'intérieur struct X vous dites au compilateur le struct a une fonction qui reçoit quelque chose de type X, mais attendez une minute, le type X n'est pas pleinement définir à ce stade!

Vous ne pouvez pas utiliser un type incomplet en tant que paramètre pour la fonction f mais vous pouvez utiliser l'adresse d'un type incomplet, donc X *.

Sur une note du site, il sera très important pour vous d'augmenter votre taux d'acceptation afin que vous obtenez des réponses pour vos futures questions et importantes pour mon ego si je suis la bonne réponse :)

+0

Oui, je comprends que nous ne pouvons pas utiliser un type incomplet en tant que paramètre pour la fonction, mais quand je déclare fonctionner dans la structure Y sous la forme void f (X); et dans la structure X, j'écris ami void Y :: f (X); alors il n'y a pas d'erreur. Comment cela est-il autorisé? –

1

Il devrait être bien pour passer l'objet incomplet X par valeur, bien que pendant la mise en œuvre de la fonction le type complet X doit être disponible indépendamment du fait que l'objet de type X soit effectivement utilisé en fonction ou non. Une déclaration de fonction est très bien avec un objet incomplet comme argument ou type de retour, sauf le type de retour covariant (pour la fonction membre) où ce type de retour doit être de type complet.

+0

Merci, mais la dernière ligne de son explication suggère que nous ne pouvons même pas déclarer comme vide f (X); –

+0

Seulement pendant la définition de la fonction, le compilateur doit connaître la taille de l'objet de type X, lorsque X est passé par valeur, de sorte qu'il puisse configurer la pile locale indépendamment du fait qu'une telle valeur soit utilisée ou non.Alors que pour une référence ou un type de pointeur, la taille du pointeur/référence est connue du compilateur, et donc il n'y a aucun problème à implémenter une telle fonction tant qu'aucun membre de l'objet x n'est pas accédé. Si vous devez accéder à des membres de x, le type complet de X doit être disponible. Probablement le livre voulait dire que X étant un type incomplet, l'implémentation de f (X *) telle que donnée n'est pas possible. – abir