friend (C++)

Dans certaines circonstances, il est utile pour une classe d’accorder un accès au niveau membre aux fonctions qui ne sont pas membres de la classe, ou à tous les membres d’une classe distincte. Ces fonctions et classes gratuites sont appelées amis, marquées par le friend mot clé. Seul l'implémenteur de classe peut déclarer qui sont ses fonctions friend. Une fonction ou une classe ne peut pas se déclarer comme un ami de n’importe quelle classe. Dans une définition de classe, utilisez la friend mot clé et le nom d’une fonction non-membre ou d’une autre classe pour lui accorder l’accès aux membres privés et protégés de votre classe. Dans une définition de modèle, un paramètre de type peut être déclaré en tant que friend.

Syntaxe

friend-declaration:
friend function-declaration
friend function-definition
friendelaborated-type-specifier;;
friend simple-type-specifier ;
friend typename-specifier ;

friend Déclarations

Si vous déclarez une friend fonction qui n’a pas été précédemment déclarée, cette fonction est exportée vers l’étendue non de classe englobante.

Les fonctions déclarées dans une friend déclaration sont traitées comme si elles avaient été déclarées à l’aide de la extern mot clé. Pour plus d’informations, consultez extern.

Bien que les fonctions avec étendue globale puissent être déclarées comme friend fonctions avant leurs prototypes, les fonctions membres ne peuvent pas être déclarées comme friend fonctions avant l’apparence de leur déclaration de classe complète. Le code suivant montre comment une telle déclaration échoue :

class ForwardDeclared;   // Class name is known.
class HasFriends
{
    friend int ForwardDeclared::IsAFriend();   // C2039 error expected
};

L’exemple précédent entre le nom ForwardDeclared de la classe dans l’étendue, mais la déclaration complète (en particulier, la partie qui déclare la fonction IsAFriend) n’est pas connue. la déclaration dans la friend classe HasFriends génère une erreur.

En C++11, il existe deux formes de déclarations d’ami pour une classe :

friend class F;
friend F;

Le premier formulaire introduit une nouvelle classe F si aucune classe existante par ce nom n’a été trouvée dans l’espace de noms le plus interne. C++11 : le deuxième formulaire n’introduit pas de nouvelle classe ; il peut être utilisé lorsque la classe a déjà été déclarée, et elle doit être utilisée lors de la déclaration d’un paramètre de type de modèle ou d’un typedeffrienden tant que .

Utilisez friend class F quand le type référencé n’a pas encore été déclaré :

namespace NS
{
    class M
    {
        friend class F;  // Introduces F but doesn't define it
    };
}

Une erreur se produit si vous utilisez friend un type de classe qui n’a pas été déclaré :

namespace NS
{
    class M
    {
        friend F; // error C2433: 'NS::F': 'friend' not permitted on data declarations
    };
}

Dans l’exemple suivant, friend F fait référence à la F classe déclarée en dehors de l’étendue de NS.

class F {};
namespace NS
{
    class M
    {
        friend F;  // OK
    };
}

Permet friend F de déclarer un paramètre de modèle en tant qu’ami :

template <typename T>
class my_class
{
    friend T;
    //...
};

Permet friend F de déclarer un typedef en tant qu’ami :

class Foo {};
typedef Foo F;

class G
{
    friend F; // OK
    friend class F // Error C2371 -- redefinition
};

Pour déclarer deux classes qui sont friends l'une de l'autre, la deuxième classe entière doit être spécifiée comme friend de la première classe. La raison de cette restriction est que le compilateur a suffisamment d'informations pour déclarer les fonctions friend uniquement au point où la deuxième classe est déclarée.

Remarque

Bien que la deuxième classe entière doive être friend de la première classe, vous pouvez sélectionner les fonctions de la première classe qui sont friends de la deuxième classe.

friend (fonctions)

Une friend fonction est une fonction qui n’est pas membre d’une classe, mais qui a accès aux membres privés et protégés de la classe. Les fonctions friend ne sont pas considérées comme des membres de classe ; il s’agit de fonctions externes normales qui reçoivent des privilèges d’accès spéciaux. Les amis ne sont pas dans l’étendue de la classe, et ils ne sont pas appelés à l’aide des opérateurs de sélection de membres (et ->), sauf s’ils sont membres d’une autre classe. Une friend fonction est déclarée par la classe qui accorde l’accès. La friend déclaration peut être placée n’importe où dans la déclaration de classe. Elle n’est pas affectée par le contrôle d’accès mot clé s.

L'exemple suivant présente une classe Point et une fonction friend, ChangePrivate. La friend fonction a accès au membre de données privé de l’objet Point qu’elle reçoit en tant que paramètre.

// friend_functions.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
class Point
{
    friend void ChangePrivate( Point & );
public:
    Point( void ) : m_i(0) {}
    void PrintPrivate( void ){cout << m_i << endl; }

private:
    int m_i;
};

void ChangePrivate ( Point &i ) { i.m_i++; }

int main()
{
   Point sPoint;
   sPoint.PrintPrivate();
   ChangePrivate(sPoint);
   sPoint.PrintPrivate();
// Output: 0
           1
}

Membres de classes en tant que friends

Les fonctions membres de classe peuvent être déclarées en tant que Friends dans d'autres classes. Prenons l’exemple suivant :

// classes_as_friends1.cpp
// compile with: /c
class B;

class A {
public:
   int Func1( B& b );

private:
   int Func2( B& b );
};

class B {
private:
   int _b;

   // A::Func1 is a friend function to class B
   // so A::Func1 has access to all members of B
   friend int A::Func1( B& );
};

int A::Func1( B& b ) { return b._b; }   // OK
int A::Func2( B& b ) { return b._b; }   // C2248

Dans l’exemple précédent, seule la fonction A::Func1( B& ) est autorisée à accéder friend à la classe B. Par conséquent, l’accès au membre _b privé est correct dans Func1 la classe A , mais pas dans Func2.

Une friend classe est une classe dont toutes les fonctions membres sont friend des fonctions d’une classe, c’est-à-dire dont les fonctions membres ont accès aux membres privés et protégés de l’autre classe. Supposez que la déclaration friend dans la classe B ait été :

friend class A;

Dans ce cas, toutes les fonctions membres de la classe A auraient été autorisées à accéder friend à la classe B. Le code suivant est un exemple de friend classe :

// classes_as_friends2.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
class YourClass {
friend class YourOtherClass;  // Declare a friend class
public:
   YourClass() : topSecret(0){}
   void printMember() { cout << topSecret << endl; }
private:
   int topSecret;
};

class YourOtherClass {
public:
   void change( YourClass& yc, int x ){yc.topSecret = x;}
};

int main() {
   YourClass yc1;
   YourOtherClass yoc1;
   yc1.printMember();
   yoc1.change( yc1, 5 );
   yc1.printMember();
}

L’amitié n’est pas mutuelle, sauf indication explicite. Dans l’exemple ci-dessus, les fonctions membres de YourClass ne peuvent pas accéder aux membres privés de YourOtherClass.

Un type managé (en C++/CLI) ne peut pas avoir friend de fonctions, friend de classes ou friend d’interfaces.

L’amitié n’est pas héritée, ce qui signifie que les classes dérivées de YourOtherClass ne peuvent pas accéder aux YourClassmembres privés. L’amitié n’est pas transitive, de sorte que les classes qui sont des amis de YourOtherClass ne peuvent pas accéder aux YourClassmembres privés de '.

L'illustration suivante montre quatre déclarations de classe : Base, Derived, aFriend et anotherFriend. Seule la classe aFriend a un accès direct aux membres privés de Base (et à tous les membres dont Base peut avoir hérité).

A diagram that shows the derivation implications of a friend relationship.

Le diagramme montre que la classe anotherFriend n’a pas de relation d’ami avec la base de classes que les amis classent aFriend. La classe aFriend est amie par classe Base, mais elle n’a pas de relation d’ami avec la classe Dérivée même si la classe Dérivée hérite de Base. Cela montre que l’héritage n’implique pas que la classe dérivée possède les mêmes amis que la classe de base.

Définitions inline friend

Les fonctions Friend peuvent être définies (en fonction d’un corps de fonction) dans les déclarations de classe. Ces fonctions sont des fonctions inline. Comme les fonctions inline des membres, elles se comportent comme si elles étaient définies immédiatement après que tous les membres de classe ont été vus, mais avant la fermeture de l’étendue de classe (à la fin de la déclaration de classe). Les fonctions friend définies à l’intérieur des déclarations de classe se trouvent dans l’étendue de la classe englobante.

Voir aussi

Mots clés