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 amis. 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 le friend mot clé et le nom d’une fonction nonmember 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
friend elaborated-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 du 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 des amis les uns des autres, la deuxième classe entière doit être spécifiée en tant qu’ami de la première classe. La raison de cette restriction est que le compilateur dispose de suffisamment d’informations pour déclarer des fonctions ami individuelles uniquement au moment où la deuxième classe est déclarée.

Remarque

Bien que l’ensemble de la deuxième classe doit être un ami à la première classe, vous pouvez sélectionner les fonctions dans la première classe seront amis de la deuxième classe.

fonctions friend

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 les mots clés de contrôle d’accès.

L’exemple suivant montre une Point classe 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 classe en tant qu’amis

Les fonctions membres de classe peuvent être déclarées en tant qu’amis 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. Supposons que la déclaration dans la friend 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 '.

La figure suivante montre quatre déclarations de classe : Base, , DerivedaFriend, et anotherFriend. Seule la classe aFriend a un accès direct aux membres privés de Base (et à tous les membres Base peuvent avoir hérités).

Diagramme montrant les implications de dérivation d’une relation ami.

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