Programmation C-C++/C++ : La couche objet/Fonctions et classes amies

Un livre de Wikilivres.
Cours de C/C++
^
C++ : La couche objet
Généralités
Extension de la notion de type du C
Déclaration de classes en C++
Encapsulation des données
Héritage
Classes virtuelles
Fonctions et classes amies
Constructeurs et destructeurs
Pointeur this
Données et fonctions membres statiques
Surcharge des opérateurs
Des entrées - sorties simplifiées
Méthodes virtuelles
Dérivation
Méthodes virtuelles pures - Classes abstraites
Pointeurs sur les membres d'une classe

Livre original de C. Casteyde

Il est parfois nécessaire d'avoir des fonctions qui ont un accès illimité aux champs d'une classe. En général, l'emploi de telles fonctions traduit un manque d'analyse dans la hiérarchie des classes, mais pas toujours. Elles restent donc nécessaires malgré tout.

De telles fonctions sont appelées des fonctions amies. Pour qu'une fonction soit amie d'une classe, il faut qu'elle soit déclarée dans la classe avec le mot clé friend.

Il est également possible de faire une classe amie d'une autre classe, mais dans ce cas, cette classe devrait peut-être être une classe fille. L'utilisation des classes amies peut traduire un défaut de conception.

Fonctions amies[modifier | modifier le wikicode]

Les fonctions amies se déclarent en faisant précéder la déclaration classique de la fonction du mot clé friend à l'intérieur de la déclaration de la classe cible. Les fonctions amies ne sont pas des méthodes de la classe cependant (cela n'aurait pas de sens puisque les méthodes ont déjà accès aux membres de la classe).

Exemple 8-8. Fonctions amies[modifier | modifier le wikicode]

class A
{
    int a;                        // Une donnée privée.
    friend void ecrit_a(int i);   // Une fonction amie.
};

A essai;

void ecrit_a(int i)
{
    essai.a=i;          // Initialise a.
    return;
}

Il est possible de déclarer amie une fonction d'une autre classe, en précisant son nom complet à l'aide de l'opérateur de résolution de portée.

Classes amies[modifier | modifier le wikicode]

Pour rendre toutes les méthodes d'une classe amies d'une autre classe, il suffit de déclarer la classe complète comme étant amie. Pour cela, il faut encore une fois utiliser le mot clé friend avant la déclaration de la classe, à l'intérieur de la classe cible. Cette fois encore, la classe amie déclarée ne sera pas une sous-classe de la classe cible, mais bien une classe de portée globale.

 Le fait, pour une classe, d'appartenir à une autre classe lui donne le droit d'accéder aux membres de sa classe hôte. Il n'est donc pas nécessaire de déclarer amies d'une classe les classes définies au sein de celle-ci. Remarquez que cette règle a été récemment modifiée dans la norme C++, et que la plupart des compilateurs refuseront aux classes incluses d'accéder aux membres non publics de leur conteneur.

Exemple 8-9. Classe amie[modifier | modifier le wikicode]

#include <stdio.h>

class Hote
{
    friend class Amie;  // Toutes les méthodes de Amie sont amies.

    int i;              // Donnée privée de la classe Hote.

public:
    Hote(void)
    {
        i=0;
        return ;
    }
};

Hote h;

class Amie
{
public:
    void print_hote(void)
    {
        printf("%d\n", h.i); // Accède à la donnée privée de h.
        return ;
    }
};

int main(void)
{
    Amie a;
    a.print_hote();
    return 0;
}

On remarquera plusieurs choses importantes. Premièrement, l'amitié n'est pas transitive. Cela signifie que les amis des amis ne sont pas des amis. Une classe A amie d'une classe B, elle-même amie d'une classe C, n'est pas amie de la classe C par défaut. Il faut la déclarer amie explicitement si on désire qu'elle le soit. Deuxièmement, les amis ne sont pas hérités. Ainsi, si une classe A est amie d'une classe B et que la classe C est une classe fille de la classe B, alors A n'est pas amie de la classe C par défaut. Encore une fois, il faut la déclarer amie explicitement. Ces remarques s'appliquent également aux fonctions amies (une fonction amie d'une classe A amie d'une classe B n'est pas amie de la classe B, ni des classes dérivées de A).