Słowo kluczowe friend pozwala określonej funkcji lub innej klasie uzyskać dostęp do prywatnych i chronionych członów klasy, w której jest zadeklarowane. Funkcje friend mogą być zarówno globalne, jak i metodami innych klas. Taka konstrukcja umożliwia realizację funkcji, które potrzebują dostępu do wewnętrznego stanu klasy, ale które logicznie nie są związane z interfejsem tej klasy.
Zaleca się używanie friend:
Uwaga:
Przykład:
class Box { int width; public: Box(int w): width(w) {} friend void printWidth(const Box &b); }; void printWidth(const Box &b) { std::cout << b.width << std::endl; }
Pytanie: Czy funkcja friend może być wirtualna?
Częsta odpowiedź: Tak, ponieważ friend to modyfikator funkcji.
Poprawna odpowiedź: Nie, funkcje friend nie mogą być wirtualne, ponieważ nie są członami klasy!
Przykład:
class Example { friend virtual void foo(); // Błąd kompilacji: wirtualny nie stosuje się do friend };
Historia: Przy projektowaniu biblioteki macierzy wszystkie operatory arytmetyczne zostały uczynione funkcjami friend dla zwiększenia wydajności, ale zapomniano o wsparciu stałości i nadto otworzono dostęp do prywatnych członów. Później pojawił się problem — w projekcie inne funkcje przypadkowo zmieniały wewnętrzny stan Matrix.
Historia: W systemie korporacyjnym klasy pomocnicze stały się dla siebie nawzajem friend w celu dzielenia się dostępem do prywatnych członów. To doprowadziło do cyklicznych zależności — dodanie nowej funkcji wymagało zmiany wszystkich powiązanych klas. Następujący refaktoryzacja zajęła tygodnie.
Historia: Do zamkniętych testów postanowiono uczynić klasę testową friend klasą produkcyjną. Kiedy pojawiło się kilka zestawów testów jednostkowych, śledzenie, które prywatne metody są faktycznie używane, stało się niemożliwe — testy zaczęły zależeć od wewnętrznej implementacji, co prowadziło do trudności w utrzymaniu kodu.