Suche…


Einführung

Gut konzipierte Klassen kapseln ihre Funktionalität ein, verbergen ihre Implementierung und bieten gleichzeitig eine saubere, dokumentierte Schnittstelle. Dies ermöglicht ein Redesign oder eine Änderung, solange die Benutzeroberfläche unverändert bleibt.

In einem komplexeren Szenario sind möglicherweise mehrere Klassen erforderlich, die auf den Implementierungsdetails der jeweils anderen basieren. Friend-Klassen und -Funktionen ermöglichen diesen Kollegen den Zugriff auf die Details der jeweils anderen, ohne die Verkapselung und das Ausblenden von Informationen der dokumentierten Schnittstelle zu beeinträchtigen.

Friend-Funktion

Eine Klasse oder Struktur kann jede Funktion deklarieren, die sie als Freund bezeichnet. Wenn eine Funktion ein Freund einer Klasse ist, kann sie auf alle geschützten und privaten Mitglieder zugreifen:

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

Zugriffsmodifizierer ändern die Semantik von Freunden nicht. Öffentliche, geschützte und private Erklärungen eines Freundes sind gleichwertig.

Freunderklärungen werden nicht vererbt. Wenn wir beispielsweise PrivateHolder subclass:

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

und versuchen, auf seine Mitglieder zuzugreifen, erhalten wir Folgendes:

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

Beachten Sie, dass PrivateHolderDerived Member-Funktion von PrivateHolderDerived nicht auf PrivateHolder::private_value zugreifen PrivateHolder::private_value , während die friend-Funktion dies tun kann.

Friend-Methode

Methoden können sowohl als Freunde als auch als Funktionen deklariert werden:

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

Freundenklasse

Eine ganze Klasse kann als Freund deklariert werden. Freundesklassenerklärung bedeutet, dass jedes Mitglied des Freundes auf private und geschützte Mitglieder der deklarierenden Klasse zugreifen kann:

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

Die Erklärung der Freundschaftsklasse ist nicht reflexiv. Wenn Klassen in beiden Richtungen einen privaten Zugriff benötigen, benötigen beide eine Freundeserklärung.

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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow