2014-09-23 1 views
1

je suis tombé sur le code suivantfonction ami et la mise en œuvre

class ExDer1 : public ExBase 
{ 
public: 
    friend int Der1Fn() 
    { 
     .... 
    } 
}; 

Je suis un peu confus ici avec

 friend int Der1Fn() 
     { 
      //This has an implementation .Why is it a friend then ? since it can access the private/protected variables of the ExDer1 class ? 
     } 

Normalement, je me attends à voir quelque chose comme le

suivant
friend int Der1Fn(); //No implementation. Indicating that the Der1Fn is a method outside this class 

ce qui signifie essentiellement qu'une fonction int Der1Fn() accéderait aux variables privées de la classe ExDer1. Cependant, cela a une implémentation. Quelqu'un pourrait-il expliquer ce que cela signifie?

Mise à jour:

Donc, si je le code suivant

class ExDer1 : public ExBase 
{ 
public: 
    friend int Der1Fn() 
    { 
     std::cout << "Hello World"; 
    } 
}; 

int main() 
{ 
    Der1Fn(); // error C3767: 'Der1Fn': candidate function(s) not accessible 
    //..... 
} 

Comment puis-je appeler Der1Fn?

+0

Où avez-vous appris que vous ne pouvez pas fournir la mise en œuvre de la fonction ami dans la classe? – P0W

+0

Je regardais exemple à http://msdn.microsoft.com/en-us/library/h2x4fzdz.aspx ils n'ont aucun exemple avec une mise en œuvre qui a déclaré ami. – Rajeshwar

+0

Cela signifie que c'est l'implémentation de la fonction. Qu'est-ce que tu ne comprends pas? –

Répondre

2

La fonction Friend (ou classe) peut également être définie à l'extérieur ou à l'intérieur d'une classe. Si vous le définissez à l'intérieur, vous devez fournir une déclaration correspondante dans la portée correcte, ou une recherche dépendant de l'argument aura lieu.

Les exemples suivants sont logiquement identiques:

Exemple 1:

int Der1Fn(); 

class ExDer1 : public ExBase 
{ 
public: 
    friend int Der1Fn() 
    { 
     .... 
    } 
}; 

Exemple 2 (recommandé):

int Der1Fn() 
{ 
    .... 
} 

class ExDer1 : public ExBase 
{ 
public: 
    friend int Der1Fn(); 
}; 

Comment appeler Der1Fn?

Aussi simple que this.

+0

vient de mettre à jour mon message. Si c'est l'équivalent d'une fonction en dehors de ma classe, comment y accéder? – Rajeshwar

+0

explication @Rajeshwar ajouté – 4pie0

+0

Etes-vous sûr Der1Fn n'a pas besoin de parenthèses dans ExDer1? – CashCow

2

Vous pouvez déclarer le corps de la fonction friend dans la définition de classe (comme pour tout type de fonction).

Cependant, la fonction friend suit les mêmes règles de base pour chaque fonction implémentée: c'est une mauvaise pratique de la déclarer dans la définition de classe (inlining, recompilations de tous les objets dépendants lors du changement, etc.).

Vous avez référencé un exemple MSDN. Ils ont juste fait l'exemple pour montrer comment la délimitation est faite. La fonction Der1Fn() est dans l'espace de noms global, pas dans ExDer1 :: Der1Fn().

Pour votre post mise à jour:

La Der1Fn de classe() n'a pas accès à de l'ExDer1 ce (ce n'est pas une partie de la classe, il est une fonction externe, pensez comme étant statique). Cependant, à l'intérieur du corps de Der1Fn(), vous pouvez accéder aux variables membres privées des objets de type ExDer1.

+0

Parfois, la mise en œuvre dans le corps de la classe est très pratique pour les classes de modèles qui ont tendance à avoir besoin en-tête que le code de toute façon .. – Pete

+1

vrai, mais on a besoin de connaître les avantages et les inconvénients. Si vous n'utilisez pas de modèles ou d'inlines, il est imprudent d'implémenter de gros blocs de code dans l'en-tête. – MichaelCMS

+0

Juste mis à jour mon poste. Si c'est une fonction externe, comment puis-je y accéder? – Rajeshwar

1

Vous feriez une fonction un ami s'il a besoin d'accéder à des membres privés de la classe, mais ne devrait pas être membre. La fonction friend peut être implémentée à l'intérieur ou à l'extérieur de la classe.Si une fonction amie est déclarée (et définie) seulement dans la classe, alors elle est définie dans l'espace de noms environnant, comme si vous l'aviez définie ici; mais il ne peut être trouvée par recherche (ADL) en fonction de l'argument - qui est, il ne peut être trouvée si elle est appelée avec un type du même espace de noms que l'un de ses arguments.

Dans ce cas, la fonction n'a pas d'arguments, donc pas du tout trouvé - c'est pourquoi vous ne pouvez pas l'appeler de main, ou d'ailleurs. Vous devrez déclarer la fonction en dehors de la classe, ainsi que dans la déclaration d'ami à l'intérieur de la classe.

Il serait plus utile si elle avait un argument du type de classe (ou un autre type scope dans le même espace); alors il se trouve lorsqu'il est appelé à ce type d'argument:

class ExDer1 : public ExBase 
{ 
public: 
    friend int Der1Fn(ExDer1 const &) 
    { 
     .... 
    } 
}; 

int main() 
{ 
    ExDer1 obj; 
    Der1Fn(obj); // Found by ADL 
} 

Définition d'un ami dans une classe est particulièrement utile pour l'opérateur qui les surcharges sont (généralement) accessible uniquement par ADL de toute façon.