Recherche…


Introduction

Des classes bien conçues encapsulent leurs fonctionnalités, cachant leur implémentation tout en fournissant une interface propre et documentée. Cela permet de redessiner ou de modifier tant que l'interface est inchangée.

Dans un scénario plus complexe, plusieurs classes reposant sur les détails d'implémentation des autres peuvent être nécessaires. Les classes et les fonctions d'ami permettent à ces pairs d'accéder aux informations des autres, sans compromettre l'encapsulation et le masquage des informations de l'interface documentée.

Fonction ami

Une classe ou une structure peut déclarer n'importe quelle fonction comme ami. Si une fonction est un ami d'une classe, elle peut accéder à tous ses membres protégés et privés:

// Forward declaration of functions.
void friend_function();
void non_friend_function();

class PrivateHolder {
public:
    PrivateHolder(int val) : private_value(val) {}
private:
    int private_value;
    // Declare one of the function as a friend.
    friend void friend_function();
};

void non_friend_function() {
    PrivateHolder ph(10);
    // Compilation error: private_value is private.
    std::cout << ph.private_value << std::endl;
}

void friend_function() {
    // OK: friends may access private values.
    PrivateHolder ph(10);
    std::cout << ph.private_value << std::endl;
}

Les modificateurs d'accès ne modifient pas la sémantique des amis. Les déclarations publiques, protégées et privées d'un ami sont équivalentes.

Les déclarations d'amis ne sont pas héritées. Par exemple, si nous sous- PrivateHolder :

class PrivateHolderDerived : public PrivateHolder {
public:
    PrivateHolderDerived(int val) : PrivateHolder(val) {}
private:
    int derived_private_value = 0;
};

et essayez d'accéder à ses membres, nous obtiendrons ce qui suit:

void friend_function() {
    PrivateHolderDerived pd(20);
    // OK.
    std::cout << pd.private_value << std::endl;
    // Compilation error: derived_private_value is private.
    std::cout << pd.derived_private_value << std::endl;
}

Notez que la fonction membre PrivateHolderDerived ne peut pas accéder à PrivateHolder::private_value , alors que la fonction friend peut le faire.

Méthode d'ami

Les méthodes peuvent être déclarées comme amis et fonctions:

class Accesser {
public:
    void private_accesser();
};

class PrivateHolder {
public:
    PrivateHolder(int val) : private_value(val) {}
    friend void Accesser::private_accesser();
private:
    int private_value;
};

void Accesser::private_accesser() {
    PrivateHolder ph(10);
    // OK: this method is declares as friend.
    std::cout << ph.private_value << std::endl;
}

Classe d'ami

Une classe entière peut être déclarée comme amie. La déclaration de classe d'amis signifie que tout membre de l'ami peut accéder aux membres privés et protégés de la classe déclarante:

class Accesser {
public:
    void private_accesser1();
    void private_accesser2();
};

class PrivateHolder {
public:
    PrivateHolder(int val) : private_value(val) {}
    friend class Accesser;
private:
    int private_value;
};

void Accesser::private_accesser1() {
    PrivateHolder ph(10);
    // OK.
    std::cout << ph.private_value << std::endl;
}

void Accesser::private_accesser2() {
    PrivateHolder ph(10);
    // OK.
    std::cout << ph.private_value + 1 << std::endl;
}

La déclaration de classe d'amis n'est pas réfléchie. Si les classes ont besoin d'un accès privé dans les deux sens, les deux ont besoin de déclarations d'amis.

class Accesser {
public:
    void private_accesser1();
    void private_accesser2();
private:
    int private_value = 0;
};

class PrivateHolder {
public:
    PrivateHolder(int val) : private_value(val) {}
    // Accesser is a friend of PrivateHolder
    friend class Accesser;
    void reverse_accesse() {
        // but PrivateHolder cannot access Accesser's members.
        Accesser a;
        std::cout << a.private_value;
    }
private:
    int private_value;
};


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow