Ricerca…


introduzione

Classi ben progettate incapsulano le loro funzionalità, nascondendo la loro implementazione e fornendo un'interfaccia pulita e documentata. Ciò consente la riprogettazione o la modifica finché l'interfaccia rimane invariata.

In uno scenario più complesso, potrebbero essere necessarie più classi che si basano sui dettagli dell'implementazione reciproca. Le classi e le funzioni di amici consentono a questi peer di accedere ai dettagli degli altri, senza compromettere l'incapsulamento e l'occultamento delle informazioni dell'interfaccia documentata.

Funzione amico

Una classe o una struttura può dichiarare qualsiasi funzione che sia amica. Se una funzione è amica di una classe, può accedere a tutti i suoi membri protetti e privati:

// 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;
}

I modificatori di accesso non alterano la semantica degli amici. Le dichiarazioni pubbliche, protette e private di un amico sono equivalenti.

Le dichiarazioni di amici non sono ereditate. Ad esempio, se eseguiamo la sottoclasse di PrivateHolder :

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

e prova ad accedere ai suoi membri, otterremo quanto segue:

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;
}

Nota che la funzione membro PrivateHolderDerived non può accedere a PrivateHolder::private_value , mentre la funzione friend può farlo.

Metodo amico

I metodi possono essere dichiarati come amici così come le funzioni:

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 di amici

Un'intera classe può essere dichiarata come amica. La dichiarazione di classe dell'amico indica che qualsiasi membro dell'amico può accedere ai membri privati ​​e protetti della classe dichiarante:

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 dichiarazione della classe di amici non è riflessiva. Se le classi hanno bisogno di un accesso privato in entrambe le direzioni, entrambe hanno bisogno di dichiarazioni di amici.

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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow