Zoeken…


Invoering

Goed ontworpen klassen bevatten hun functionaliteit, verbergen hun implementatie en bieden een schone, gedocumenteerde interface. Dit maakt herontwerp of wijziging mogelijk zolang de interface ongewijzigd blijft.

In een complexer scenario kunnen meerdere klassen nodig zijn die afhankelijk zijn van elkaars implementatiedetails. Vriendklassen en functies geven deze collega's toegang tot elkaars details, zonder afbreuk te doen aan de inkapseling en het verbergen van informatie van de gedocumenteerde interface.

Vriend functie

Een klasse of een structuur kan elke functie verklaren die het vriend is. Als een functie een vriend van een klas is, heeft deze toegang tot alle beveiligde en privéleden:

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

Toegangsmodificaties veranderen de semantiek van vrienden niet. Openbare, beschermde en privéverklaringen van een vriend zijn gelijkwaardig.

Vriendsverklaringen worden niet geërfd. Als we bijvoorbeeld PrivateHolder :

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

en proberen toegang te krijgen tot de leden, krijgen we het volgende:

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

Merk op dat de PrivateHolderDerived geen toegang heeft tot PrivateHolder::private_value , terwijl de vriendenfunctie dit wel kan.

Vriend methode

Methoden kunnen als vrienden worden verklaard, evenals functies:

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

Vriendenklasse

Een hele klas kan als vriend worden verklaard. Verklaring van de vriendschapsklasse betekent dat elk lid van de vriend toegang heeft tot privé- en beschermde leden van de klasse die verklaart:

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

Verklaring van vriendschapsklassen is niet wederkerend. Als klassen privétoegang in beide richtingen nodig hebben, hebben ze allebei vriendenverklaringen nodig.

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow