Czytałem przez C ++ FAQ i byłem ciekawy friend
deklaracji. Osobiście nigdy go nie używałem, ale interesuje mnie odkrywanie języka.
Jaki jest dobry przykład używania friend
?
Trochę dłużej czytając FAQ Podoba mi się pomysł <<
>>
przeciążania operatora i dodawania go jako przyjaciela tych klas. Nie jestem jednak pewien, w jaki sposób nie przerywa to enkapsulacji. Kiedy te wyjątki mogą pozostać w ramach surowej zasady, którą jest OOP?
c++
oop
encapsulation
friend
Peter Mortensen
źródło
źródło
Odpowiedzi:
Po pierwsze (IMO) nie słuchaj ludzi, którzy twierdzą, że
friend
nie jest to przydatne. To jest użyteczne. W wielu sytuacjach będziesz mieć obiekty z danymi lub funkcjami, które nie mają być publicznie dostępne. Jest to szczególnie prawdziwe w przypadku dużych baz kodowych z wieloma autorami, którzy mogą jedynie powierzchownie znać różne obszary.Istnieją alternatywy dla specyfikatora przyjaciela, ale często są one uciążliwe (klasy betonowe na poziomie cpp / maskowane typy typef) lub niezawodnie (komentarze lub konwencje nazw funkcji).
Na odpowiedź;
Specyfikator
friend
umożliwia wyznaczonej klasie dostęp do chronionych danych lub funkcji w obrębie klasy, czyniąc wypowiedź znajomego. Na przykład w poniższym kodzie każdy może poprosić dziecko o swoje imię, ale tylko matka i dziecko mogą zmienić imię.Możesz pójść dalej tym prostym przykładem, rozważając bardziej złożoną klasę, taką jak Window. Całkiem prawdopodobne, że okno będzie zawierało wiele funkcji / elementów danych, które nie powinny być publicznie dostępne, ale SĄ wymagane przez powiązaną klasę, taką jak WindowManager.
źródło
friend
poprawia enkapsulację.friend
zapewnia członkom selektywny dostęp , podobnie jak toprotected
robi. Każda drobiazgowa kontrola jest lepsza niż przyznanie publicznego dostępu. Inne języki również definiują mechanizmy dostępu selektywnego, rozważmy C #internal
. Najbardziej negatywna krytykafriend
związana z używaniem jest związana z ściślejszym sprzężeniem, co ogólnie uważa się za coś złego. Jednak w niektórych przypadkach ściślejsze sprzężenie jest dokładnie tym, czego chcesz ifriend
daje ci tę moc.friend
, niż na dawaniu motywującego przykładu. Przykład Window / WindowManager jest lepszy niż pokazany przykład, ale zbyt niejasny. Ta odpowiedź nie dotyczy również części enkapsulacji pytania.W pracy używamy znajomych do intensywnego testowania kodu . Oznacza to, że możemy zapewnić właściwe enkapsulację i ukrywanie informacji dla głównego kodu aplikacji. Ale możemy też mieć osobny kod testowy, który używa znajomych do sprawdzania stanu wewnętrznego i danych do testowania.
Wystarczy powiedzieć, że nie użyłbym słowa kluczowego „przyjaciel” jako niezbędnego elementu twojego projektu.
źródło
Słowo
friend
kluczowe ma wiele dobrych zastosowań. Oto dwa zastosowania natychmiast widoczne dla mnie:Definicja przyjaciela
Definicja znajomego pozwala zdefiniować funkcję w zakresie klasy, ale funkcja ta nie będzie zdefiniowana jako funkcja składowa, ale jako wolna funkcja otaczającej przestrzeni nazw i nie będzie widoczna normalnie, z wyjątkiem wyszukiwania zależnego od argumentów. Dzięki temu jest szczególnie przydatny w przypadku przeciążenia operatora:
Prywatna klasa bazowa CRTP
Czasami okazuje się, że polityka potrzebuje dostępu do klasy pochodnej:
W tej odpowiedzi znajdziesz nieprzygotowany przykład . Inny kod używający tego jest w tej odpowiedzi. Baza CRTP rzutuje ten wskaźnik, aby móc uzyskać dostęp do pól danych klasy pochodnej za pomocą wskaźników elementów danych.
źródło
P<C>
wtemplate<template<typename> class P> class C : P<C> {};
stwierdzające, „Korzystanie z szablonu klasy C wymaga argumentów szablonu”. Masz takie same problemy lub może znasz rozwiązanie?FlexibleClass
wewnątrzFlexibleClass
powinno domyślnie odnosić się do jego własnego typu.@roo : Hermetyzacja nie jest tu zerwana, ponieważ sama klasa decyduje, kto może uzyskać dostęp do jej prywatnych członków. Hermetyzacja zostałaby zerwana tylko wtedy, gdyby mogła być spowodowana spoza klasy, np.
operator <<
Gdybyś ogłosił „Jestem przyjacielem klasyfoo
”.friend
zastępuje użyciepublic
, a nie użycieprivate
!W rzeczywistości C ++ FAQ już na to odpowiada .
źródło
friend
nie jest wyjątkiem. Jedyną prawdziwą obserwacją jest to, że C ++ zapewnia enkapsulację tylko w czasie kompilacji. I nie potrzebujesz więcej słów, żeby to powiedzieć. Reszta to pierdoły. Podsumowując: ta sekcja FQA nie jest warta wspomnienia.Kanonicznym przykładem jest przeciążenie operatora <<. Innym powszechnym zastosowaniem jest umożliwienie klasie pomocnika lub administratora dostępu do wewnętrznych elementów.
Oto kilka wskazówek, które słyszałem o znajomych w C ++. Ten ostatni jest szczególnie niezapomniany.
źródło
friend
Chyba kanoniczny brak używania .Jak przerwałoby to enkapsulację?
Przerywasz enkapsulację, gdy zezwalasz na nieograniczony dostęp do elementu danych. Rozważ następujące klasy:
c1
jest oczywiście nie obudowane. Każdy może w nim czytać i modyfikowaćx
. Nie mamy możliwości egzekwowania jakiejkolwiek kontroli dostępu.c2
jest oczywiście zamknięty. Nie ma publicznego dostępu dox
. Wszystko, co możesz zrobić, to wywołaćfoo
funkcję, która wykonuje pewne znaczące operacje na klasie .c3
? Czy to jest mniej zamknięte? Czy pozwala na nieograniczony dostępx
? Czy umożliwia dostęp do nieznanych funkcji?Nie. Pozwala dokładnie jednej funkcji na dostęp do prywatnych członków klasy. Tak jak
c2
zrobiłem. I podobniec2
, jedyną funkcją, która ma dostęp, nie jest „jakaś losowa, nieznana funkcja”, ale „funkcja wymieniona w definicji klasy”. Podobnie jakc2
widzimy, po prostu patrząc na definicje klas, pełną listę osób, które mają dostęp.Jak dokładnie jest to mniej zamknięte? Ta sama ilość kodu ma dostęp do prywatnych członków klasy. I każdy, kto ma dostęp, jest wymieniony w definicji klasy.
friend
nie przerywa enkapsulacji. To sprawia, że niektórzy programiści Java czują się niekomfortowo, ponieważ kiedy mówią „OOP”, w rzeczywistości mają na myśli „Java”. Kiedy mówią „Encapsulation”, nie oznacza to „członkowie prywatne muszą być chronione przed arbitralnymi dostępów”, ale „klasy Java, gdzie funkcjonuje tylko możliwość dostępu do prywatnych członków są członkowie klasy”, choć jest to kompletny nonsens dla kilka powodów .Po pierwsze, jak już pokazano, jest to zbyt restrykcyjne. Nie ma powodu, dla którego metody znajomych nie powinny robić tego samego.
Po drugie, nie jest to wystarczająco restrykcyjne . Rozważ czwartą klasę:
To, zgodnie z wyżej wspomnianą mentalnością Javy, jest doskonale zamknięte. A jednak pozwala absolutnie każdemu czytać i modyfikować x . Jak to w ogóle ma sens? (wskazówka: nie ma)
Konkluzja: Hermetyzacja polega na możliwości kontrolowania, które funkcje mogą uzyskiwać dostęp do członków prywatnych. To nie o dokładnie gdzie znajdują się definicje tych funkcji.
źródło
Inna popularna wersja przykładu Andrew, przerażający kodeks
Zamiast martwić się, że obie linie są zawsze wykonywane razem i w spójnej kolejności, możesz ustawić metody na prywatne i mieć funkcję przyjaciela, aby wymusić spójność:
Innymi słowy, możesz zmniejszyć interfejsy publiczne i wymusić niezmienniki, które przecinają klasy i obiekty w funkcjach znajomych.
źródło
addChild
funkcji członka ustawić również element nadrzędny?setParent
znajomości, ponieważ nie chcesz zezwalać klientom na zmianę rodzica, ponieważ będziesz nim zarządzać w kategoriiaddChild
/removeChild
funkcji.Kontrolujesz prawa dostępu dla członków i funkcji, korzystając z prawa prywatnego / chronionego / publicznego? więc zakładając, że idea każdego z tych 3 poziomów jest jasna, powinno być jasne, że czegoś nam brakuje ...
Deklaracja chronionego członka / funkcji na przykład jest dość ogólna. Mówisz, że ta funkcja jest niedostępna dla wszystkich (z wyjątkiem oczywiście odziedziczonego dziecka). Ale co z wyjątkami? każdy system bezpieczeństwa pozwala ci mieć jakąś „białą listę”, prawda?
Tak więc przyjaciel pozwala elastycznie izolować stałe obiekty skalne, ale pozwala stworzyć „lukę” dla rzeczy, które uważasz za uzasadnione.
Myślę, że ludzie mówią, że nie jest to potrzebne, ponieważ zawsze istnieje projekt, który da sobie z tym radę. Myślę, że jest to podobne do dyskusji na temat zmiennych globalnych: nigdy nie powinieneś ich używać, zawsze istnieje sposób na obejście się bez nich ... ale w rzeczywistości widzisz przypadki, w których jest to (prawie) najbardziej elegancki sposób. .. Myślę, że to samo dotyczy przyjaciół.
cóż, to nie jest dokładnie tak na to patrzeć. Chodzi o to, aby kontrolować, kto ma dostęp do tego, co ma, ale nie ma funkcji ustawień, ma z tym niewiele wspólnego.
źródło
friend
luka? Umożliwia metodom wymienionym w klasie dostęp do jej prywatnych członków. Nadal nie pozwala na dostęp do nich dowolnego kodu. Jako taki nie różni się niczym od funkcji członka publicznego.Znalazłem przydatne miejsce do korzystania z dostępu do znajomych: Najmniejsze prywatne funkcje.
źródło
Przyjaciel przydaje się, gdy budujesz kontener i chcesz zaimplementować iterator dla tej klasy.
źródło
W firmie, w której wcześniej pracowałem, pojawił się interesujący problem, w którym użyliśmy znajomego do przyzwoitego afektu. Pracowałem w naszym dziale ramowym, stworzyliśmy podstawowy system poziomu silnika nad naszym niestandardowym systemem operacyjnym. Wewnętrznie mieliśmy strukturę klas:
Wszystkie te klasy były częścią frameworka i były prowadzone przez nasz zespół. Gry produkowane przez firmę zostały zbudowane na bazie tego środowiska pochodzącego od jednego z dzieci Games. Problem polegał na tym, że gra miała interfejsy do różnych rzeczy, do których SinglePlayer i TwoPlayer potrzebowali dostępu, ale że nie chcieliśmy ujawniać się poza klasami frameworka. Rozwiązaniem było uczynienie tych interfejsów prywatnymi i umożliwienie dostępu do nich TwoPlayer i SinglePlayer poprzez przyjaźń.
Prawdę mówiąc, cały ten problem mógł zostać rozwiązany przez lepszą implementację naszego systemu, ale byliśmy zamknięci w tym, co mieliśmy.
źródło
Krótka odpowiedź brzmiałaby: użyj znajomego, gdy rzeczywiście się poprawi enkapsulację. Poprawa czytelności i użyteczności (operatory << i >> są kanonicznym przykładem) jest również dobrym powodem.
Jeśli chodzi o przykłady poprawy enkapsulacji, klasy specjalnie zaprojektowane do pracy z elementami wewnętrznymi innych klas (przychodzą na myśl klasy testowe) są dobrymi kandydatami.
źródło
<<
i>>
zwykle są przyjaciółmi, a nie członkami, ponieważ uczynienie ich członkami sprawiłoby, że korzystanie z nich byłoby niewygodne. Oczywiście mówię o przypadku, gdy operatorzy ci muszą uzyskać dostęp do prywatnych danych; w przeciwnym razie przyjaźń jest bezużyteczna.operator<<
ioperator>>
członkowie klasy wartości zamiast osób niebędących członkami lub członkamii|ostream
nie zapewniłyby pożądanej składni, a ja tego nie sugeruję. „ Mówię o przypadku, w którym operatorzy ci muszą uzyskać dostęp do prywatnych danych ”. Nie do końca rozumiem, dlaczego operatorzy wejścia / wyjścia musieliby uzyskać dostęp do prywatnych członków.Twórca C ++ twierdzi, że nie łamie żadnej zasady enkapsulacji, a ja go zacytuję:
Jest więcej niż jasne ...
źródło
Inne zastosowanie: przyjaciel (+ wirtualne dziedziczenie) może być użyty, aby uniknąć wywodzenia się z klasy (aka: „uczyń klasę możliwą do podzielenia”) => 1 , 2
Od 2 :
źródło
Aby zrobić TDD wiele razy użyłem słowa kluczowego „przyjaciel” w C ++.
Czy przyjaciel może wiedzieć o mnie wszystko?
Zaktualizowano: Znalazłem tę cenną odpowiedź na temat słowa kluczowego „przyjaciel” ze strony Bjarne Stroustrup .
źródło
Musisz bardzo uważać, kiedy i gdzie używasz
friend
słowa kluczowego, i tak jak ty, używałem go bardzo rzadko. Poniżej znajduje się kilka uwag dotyczących używaniafriend
i alternatyw.Powiedzmy, że chcesz porównać dwa obiekty, aby sprawdzić, czy są one równe. Możesz:
Problem z pierwszą opcją polega na tym, że może to być DUŻO akcesoriów, które jest (nieco) wolniejsze niż bezpośredni dostęp do zmiennych, trudniejsze do odczytania i kłopotliwe. Problem z drugim podejściem polega na tym, że całkowicie przełamujesz enkapsulację.
Byłoby fajnie, gdybyśmy mogli zdefiniować funkcję zewnętrzną, która nadal mogłaby uzyskać dostęp do prywatnych członków klasy. Możemy to zrobić za pomocą
friend
słowa kluczowego:Metoda
equal(Beer, Beer)
ma teraz bezpośredni dostęp doa
ib
„s członków prywatnych (które mogą byćchar *brand
,float percentAlcohol
itp Jest to raczej wymyślony przykład, należy wcześniej zastosowaćfriend
do przeciążony== operator
, ale my się do tego.Kilka rzeczy do zapamiętania:
friend
NIE jest funkcją składową klasypublic
!)Naprawdę używam tylko
friends
wtedy, gdy znacznie trudniej jest to zrobić w drugą stronę. Jako inny przykład, funkcje wielu matematyki wektorowe są często tworzone jakofriends
ze względu na interoperacyjnośćMat2x2
,Mat3x3
,Mat4x4
,Vec2
,Vec3
,Vec4
, itd. A to jest po prostu o wiele łatwiej być przyjaciółmi, a nie trzeba używać akcesorów wszędzie. Jak wskazano,friend
często jest przydatny, gdy jest stosowany do<<
(bardzo przydatny do debugowania)>>
i może==
operatora, ale może być również używany do czegoś takiego:Jak mówię, wcale nie używam
friend
zbyt często, ale od czasu do czasu jest to tylko to, czego potrzebujesz. Mam nadzieję że to pomoże!źródło
W odniesieniu do operatora << i operatora >> nie ma dobrego powodu, aby zaprzyjaźnić tych operatorów. To prawda, że nie powinny to być funkcje członkowskie, ale nie muszą też być przyjaciółmi.
Najlepiej jest utworzyć funkcje drukowania publicznego (ostream &) i czytania (istream &). Następnie napisz operator << i operator >> pod względem tych funkcji. Daje to dodatkową korzyść polegającą na umożliwieniu wirtualizacji tych funkcji, co zapewnia wirtualną serializację.
źródło
Używam słowa kluczowego „przyjaciel” tylko do najbardziej chronionych funkcji. Niektórzy powiedzą, że nie powinieneś testować chronionych funkcji. Uważam jednak to bardzo przydatne narzędzie podczas dodawania nowej funkcjonalności.
Jednak nie używam tego słowa kluczowego bezpośrednio w deklaracjach klas, zamiast tego używam sprytnego hackowania szablonu, aby osiągnąć ten cel:
Dzięki temu mogę wykonać następujące czynności:
Działa na GCC i MSVC przynajmniej.
źródło
W C ++ słowo kluczowe „przyjaciel” jest przydatne w przeciążaniu operatora i tworzeniu mostu.
Teraz pierwsza opcja nie jest dobra, ponieważ jeśli musimy ponownie przeciążyć tego operatora dla innej klasy, musimy ponownie wprowadzić zmiany w klasie „ostream”.1.) Słowo kluczowe przyjaciela w przeciążeniu operatora:
Przykładem przeciążenia operatora jest: Załóżmy, że mamy klasę „Punkt”, która ma dwie zmienne zmienne
„x” (dla współrzędnej x) i „y” (dla współrzędnej y). Teraz musimy przeciążać
"<<"
(operator ekstrakcji) tak, że jeśli"cout << pointobj"
wywołamy, to wypisze współrzędną xiy (gdzie pointobj jest obiektem klasy Point). Aby to zrobić, mamy dwie opcje:Właśnie dlatego druga opcja jest najlepsza. Teraz kompilator może wywoływać
"operator <<()"
funkcję:Ponieważ wdrożyliśmy przeciążanie w klasie Point. Aby wywołać tę funkcję bez obiektu, musimy dodać
"friend"
słowo kluczowe, ponieważ możemy wywołać funkcję znajomego bez obiektu. Teraz deklaracja funkcji będzie jak:"friend ostream &operator<<(ostream &cout, Point &pointobj);"
2.) Słowo kluczowe przyjaciela przy tworzeniu mostu:
Załóżmy, że musimy stworzyć funkcję, w której musimy uzyskać dostęp do prywatnego członka dwóch lub więcej klas (ogólnie określanych jako „most”). Jak to zrobić:
Aby uzyskać dostęp do prywatnego członka klasy, powinien on być członkiem tej klasy. Aby uzyskać dostęp do prywatnego członka innej klasy, każda klasa powinna zadeklarować tę funkcję jako funkcję przyjaciela. Na przykład: Załóżmy, że istnieją dwie klasy A i B. Funkcja
"funcBridge()"
chce uzyskać dostęp do prywatnego członka obu klas. Następnie obie klasy powinny zadeklarować"funcBridge()"
jako:friend return_type funcBridge(A &a_obj, B & b_obj);
Myślę, że pomogłoby to zrozumieć słowo kluczowe znajomego.
źródło
Jak wynika z odniesienia do deklaracji znajomego :
Przypominamy, że w niektórych odpowiedziach występują błędy techniczne, które mówią, że
friend
mogą odwiedzać tylko chronionych członków.źródło
Przykład drzewa jest całkiem dobrym przykładem: posiadanie obiektu zaimplementowanego w kilku różnych klasach bez relacji dziedziczenia.
Być może możesz też potrzebować ochrony konstruktora i zmusić ludzi do korzystania z fabryki „przyjaciela”.
... Ok, szczerze mówiąc, bez tego możesz żyć.
źródło
Nie, to tylko przyjaźń jednokierunkowa: `(
źródło
Jednym konkretnym przykładem, którego używam,
friend
jest tworzenie klas Singleton .friend
Słów kluczowych pozwala mi utworzyć funkcję dostępowej, która jest bardziej zwięzły niż zawsze o „GetInstance ()” metodę na klasy.źródło
friend
nie nie potrzebują szczególnej „Uzasadnienie”, podczas dodawania funkcji członek nie.Funkcje i klasy znajomych zapewniają bezpośredni dostęp do prywatnych i chronionych członków klasy, aby uniknąć przerwania enkapsulacji w ogólnym przypadku. Najczęściej używa się ostreamu: chcielibyśmy móc pisać:
Może to jednak wymagać dostępu do prywatnych danych Point, dlatego definiujemy przeciążonego operatora
Istnieją jednak oczywiste konsekwencje enkapsulacji. Po pierwsze, teraz klasa lub funkcja przyjaciela ma pełny dostęp do WSZYSTKICH członków klasy, nawet tych, którzy nie odnoszą się do jej potrzeb. Po drugie, implementacje klasy i przyjaciela są teraz powiązane do tego stopnia, że wewnętrzna zmiana w klasie może złamać przyjaciela.
Jeśli postrzegasz przyjaciela jako rozszerzenie klasy, to nie jest to logicznie rzecz biorąc problem. Ale w takim razie dlaczego przede wszystkim trzeba było spearingować przyjaciela.
Aby osiągnąć to samo, co zamierzają osiągnąć „przyjaciele”, ale bez przerywania enkapsulacji, można to zrobić:
Hermetyzacja nie jest zerwana, klasa B nie ma dostępu do wewnętrznej implementacji w A, ale wynik jest taki sam, jakbyśmy zadeklarowali B jako przyjaciela A. Kompilator zoptymalizuje wywołania funkcji, więc spowoduje to takie same instrukcje jako bezpośredni dostęp.
Myślę, że użycie „przyjaciela” jest po prostu skrótem z uzasadnioną korzyścią, ale określonym kosztem.
źródło
To może nie być rzeczywista sytuacja użycia, ale może pomóc zilustrować użycie znajomego między klasami.
ClubHouse
Klasa członków
Udogodnienia
Jeśli spojrzysz na związek tych klas tutaj; ClubHouse posiada wiele różnych rodzajów członkostwa i dostęp do członkostwa. Wszyscy członkowie pochodzą z klasy super lub podstawowej, ponieważ wszyscy mają wspólny identyfikator, a typ wyliczony, który jest wspólny, a klasy zewnętrzne mogą uzyskiwać dostęp do swoich identyfikatorów i typów poprzez funkcje dostępu znajdujące się w klasie podstawowej.
Jednak dzięki takiej hierarchii członków i klas pochodnych oraz ich relacji z klasą ClubHouse jedyną klasą pochodną, która ma „specjalne uprawnienia”, jest klasa VIPMember. Klasa podstawowa i pozostałe 2 klasy pochodne nie mogą uzyskać dostępu do metody joinVIPEvent () ClubHouse, ale klasa członka VIP ma takie przywileje, jakby miała pełny dostęp do tego zdarzenia.
Tak więc z VIPMember i ClubHouse jest to dwukierunkowa ulica dostępu, gdzie pozostałe Klasy Członków są ograniczone.
źródło
Podczas implementacji algorytmów drzewa dla klasy, kod ramowy, który dał nam prof, miał klasę drzewa jako przyjaciela klasy węzłów.
Naprawdę nie przynosi to żadnego pożytku, oprócz umożliwienia dostępu do zmiennej składowej bez użycia funkcji ustawiania.
źródło
Możesz korzystać z przyjaźni, gdy różne klasy (nie dziedzicząc jednej od drugiej) korzystają z prywatnych lub chronionych członków drugiej klasy.
z http://www.cplusplus.com/doc/tutorial/inheritance/ .
Możesz zobaczyć ten przykład, w którym metoda nie będąca członkiem uzyskuje dostęp do prywatnych członków klasy. Ta metoda musi być zadeklarowana w tej klasie jako przyjaciel klasy.
źródło
Prawdopodobnie coś pominąłem z powyższych odpowiedzi, ale innym ważnym pojęciem w enkapsulacji jest ukrywanie implementacji. Ograniczenie dostępu do prywatnych członków danych (szczegóły implementacji klasy) pozwala znacznie łatwiej modyfikować kod później. Jeśli znajomy uzyskuje bezpośredni dostęp do danych prywatnych, wszelkie zmiany w polach danych implementacyjnych (dane prywatne), złam kod, który uzyskuje dostęp do tych danych. Korzystanie z metod dostępu w większości eliminuje to. Myślę, że to dość ważne.
źródło
Państwo mogłoby stosować się do zasad najsurowszych i najczystsza OOP i upewnić się, że żaden z członków danych dla dowolnej klasy nawet akcesorów tak, że wszystkie obiekty muszą być jedynymi, które mogą wiedzieć o swoich danych z jedynym sposobem działania na nich jest poprzez pośrednie wiadomości , tj. metody.
Ale nawet C # ma wewnętrzne słowo kluczowe widoczności, a Java ma domyślną dostępność poziomu pakietu dla niektórych rzeczy. C ++ jest bliżej ideału OOP, minimalizując kompromis w zakresie widoczności w klasie, określając dokładnie, która inna klasa i tylko inne klasy mogą się w to zapoznać.
Tak naprawdę nie używam C ++, ale gdyby C # miał znajomych , zrobiłbym to zamiast wewnętrznego modyfikatora asemblera , którego faktycznie używam. Tak naprawdę nie psuje to incapsulation, ponieważ jednostką wdrażania w .NET jest zestaw.
Ale jest jeszcze atrybut InternalsVisibleTo Attribute (otherAssembly), który działa jak mechanizm zaprzyjaźnienia między zespołami . Microsoft używa tego do zestawów projektantów wizualnych .
źródło
Znajomi są również przydatni w przypadku oddzwaniania. Można zaimplementować wywołania zwrotne jako metody statyczne
gdzie
callback
połączenialocalCallback
wewnętrzne orazclientData
ma w nim swoją instancję. W mojej opinii,lub...
To pozwala na to, aby przyjaciel był zdefiniowany wyłącznie w cpp jako funkcja w stylu c, a nie zagracałaby klasę.
Podobnie, wzór, który często widziałem, polega na ułożeniu wszystkiego naprawdę prywatnych członków klasy w innej klasie, która jest zadeklarowana w nagłówku, zdefiniowana w cpp i zaprzyjaźniona. Pozwala to programowi kodującemu na ukrywanie złożoności i wewnętrznego działania klasy przed użytkownikiem nagłówka.
W nagłówku:
W cpp
Łatwiej jest ukryć rzeczy, które nie muszą widzieć w ten sposób.
źródło