Szukaj…


Wprowadzenie

Dobrze zaprojektowane klasy zawierają ich funkcjonalność, ukrywając ich implementację, zapewniając jednocześnie przejrzysty, udokumentowany interfejs. Umożliwia to przeprojektowanie lub zmianę, o ile interfejs pozostaje niezmieniony.

W bardziej złożonym scenariuszu może być wymagane wiele klas, które opierają się na wzajemnych szczegółach implementacji. Klasy i funkcje znajomych pozwalają tym rówieśnikom na dostęp do swoich danych, bez uszczerbku dla enkapsulacji i ukrywania informacji w udokumentowanym interfejsie.

Funkcja przyjaciela

Klasa lub struktura może zadeklarować dowolną funkcję, którą jest przyjacielem. Jeśli funkcja jest przyjacielem klasy, może uzyskać dostęp do wszystkich chronionych i prywatnych członków:

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

Modyfikatory dostępu nie zmieniają semantyki znajomych. Publiczne, chronione i prywatne deklaracje znajomego są równoważne.

Deklaracje znajomych nie są dziedziczone. Na przykład, jeśli PrivateHolder :

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

i spróbuj uzyskać dostęp do jego członków, otrzymamy:

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

Zauważ, że PrivateHolderDerived członkowska PrivateHolderDerived nie może uzyskać dostępu do PrivateHolder::private_value , podczas gdy funkcja znajomego może to zrobić.

Metoda przyjaciela

Metody mogą być deklarowane jako przyjaciele, a także funkcje:

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

Klasa przyjaciela

Cała klasa może zostać uznana za przyjaciela. Deklaracja klasy znajomego oznacza, że każdy członek znajomego może uzyskać dostęp do prywatnych i chronionych członków deklarującej klasy:

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

Deklaracja klasy przyjaciół nie jest zwrotna. Jeśli zajęcia potrzebują prywatnego dostępu w obu kierunkach, oba potrzebują deklaracji znajomych.

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow