Do czego służy słowo kluczowe „przyjaciel”?

11

Czy możesz mi wyjaśnić, dlaczego friendsłowo kluczowe jest preferowane w celu przyznania praw dostępu do prywatnych danych klasy?

Dalton
źródło
1
Jeśli zapytasz, dlaczego byłeś friendpreferowany, jakie inne sposoby zazwyczaj używasz do uzyskania dostępu do danych klasy prywatnej z zewnątrz?
Benjamin Bannier,
@honk „Preferowane” może być niewłaściwym słowem w tym miejscu. Zredagowałem większość postu, aby poprawić gramatykę i tak dalej, i wybrałem oryginalne słowo, ale myślę, że może istnieć tutaj bariera językowa.
Adam Lear
Nie wiem, bo dzisiaj przypadkiem przeczytałem o przyjacielu. a artykuł mówi, że jeśli nie użyję przyjaciela, stworzę klasę monolit.
Dalton,

Odpowiedzi:

17

Przyjaciel to klasyczny sposób na rozszerzenie interfejsu klasy.
Ale wielką zaletą jest to, że przyjaciel wyraźnie dokumentuje twój zamiar ścisłego powiązania określonych przedmiotów z klasą.

Uwaga: Korzystając z przyjaciela, ściśle wiążesz znajomych z klasą.

Doskonałym przykładem są operatory strumieniowe w C ++

class Plop
{
    private:
        int  value;
        friend std::ostream& operator<<(std::ostream& stream, Plop const& data);
        friend std::istream& operator>>(std::istream& stream, Plop&       data);
};

std::ostream& operator<<(std::ostream& stream, Plop const& data)
{
     return stream << data.value << " ";
}
std::istream& operator>>(std::istream& stream, Plop&       data)
{
     return stream >> data.value;
}

Rozszerzamy publiczny interfejs klasy Plop w sposób, który pozwala nam przesyłać strumieniowo obiekt do i ze strumienia, ale bez ujawniania wewnętrznej implementacji lub powodowania problemów związanych z przyszłymi implementacjami, wymagając użycia metod get / set, które muszą być utrzymywane (ponieważ byłyby częścią publicznego interfejsu), nawet jeśli wewnętrzna implementacja zostanie zmieniona.

Uwaga: NIE przerywa to enkapsulacji, ale ściśle wiąże operatorów strumienia z implementacją klasy Plop (tzn. Każda zmiana implementacji klasy Plop będzie wymagała zmiany w implementacji operatorów strumienia). Ale jest to oczekiwane. Wszystkie części interfejsu publicznego (w tym metody publiczne / chronione) są ściśle związane z implementacją.

Ale uwaga: Udokumentowałeś to wiązanie jako część deklaracji klasy.

Uwaga: nie odnosiłbym się do znajomego jako preferowanego sposobu ujawnienia prywatnych danych. Nadużywanie znajomego może być równie złe, jak ujawnianie implementacji. Podobnie jak wszystkie funkcje językowe, należy z niego rozsądnie korzystać.

Martin York
źródło
Gdybyś mógł publicznie uzyskać dostęp do danych (np. Poprzez getter), czy zamiast tego użyłbyś bezpłatnej funkcji?
Ioanna,