Třída přátel - Friend class
A třída přátel v C ++ může přistupovat k soukromé a chráněné členové třída ve kterém je deklarován jako přítel.[1] Významné použití třídy přátel je pro část datové struktury, představovanou třídou, k poskytnutí přístupu k hlavní třídě představující tuto datovou strukturu. Mechanismus třídy přátel umožňuje rozšířit úložiště a přístup k částem při zachování správné zapouzdření, jak to vidí uživatelé datové struktury.
Podobně jako třída přátel, a funkce přítele je funkce který má přístup k soukromým a chráněným členům třídy, ve které je deklarován jako přítel.
Příklad
Následující příklad ukazuje použití třídy přátel pro datovou strukturu grafu, kde je graf reprezentován hlavní třídou Graph a vrcholy grafu jsou reprezentovány třídou Vertex.
#zahrnout <iostream>#zahrnout <memory>#zahrnout <string>#zahrnout <unordered_set>třída Graf;třída Vrchol { veřejnost: explicitní Vrchol(std::tětiva název) : hrany_(), název_(std::přestěhovat se(název)) {} auto začít() konst { vrátit se hrany_.cbegin(); } auto konec() konst { vrátit se hrany_.postoupit(); } konst auto& název() konst { vrátit se název_; } soukromé: // Vertex dává přístupová práva ke Graph. příteli třída Graf; std::unordered_set<Vrchol*> hrany_; std::tětiva název_;};třída Graf { veřejnost: ~Graf() { zatímco (!vrcholy_.prázdný()) { auto vrchol = vrcholy_.začít(); RemoveVertex(*vrchol); } } auto AddVertex(konst std::tětiva& název) -> Vrchol* { auto vrchol = std::make_unique<Vrchol>(název); auto iter = vrcholy_.vložit(vrchol.dostat()); vrátit se vrchol.uvolnění(); } prázdnota RemoveVertex(Vrchol* vrchol) { vrcholy_.vymazat(vrchol); vymazat vrchol; } auto AddEdge(Vrchol* z, Vrchol* na) { // Graph má přístup k soukromým polím Vertexu, protože Vertex deklaroval Graph jako // přítel. z->hrany_.vložit(na); } auto začít() konst { vrátit se vrcholy_.cbegin(); } auto konec() konst { vrátit se vrcholy_.postoupit(); } soukromé: std::unordered_set<Vrchol*> vrcholy_;};
Zapouzdření
Správné použití tříd přátel zvyšuje zapouzdření, protože umožňuje rozšířit soukromý přístup k datové struktuře na její části --- které datová struktura vlastní --- bez povolení soukromého přístupu k jakékoli jiné externí třídě. Tímto způsobem zůstane datová struktura chráněna před náhodnými pokusy o rozbití invarianty datové struktury zvenčí.
Je důležité si všimnout, že třída si nemůže dovolit přístup k soukromé části jiné třídy; to by rozbilo zapouzdření. Třída spíše dává přístup ke svým soukromým částem jiné třídě - prohlášením této třídy za přítele. V příkladu grafu se Graph nemůže prohlásit za přítele Vertex. Spíše Vertex prohlašuje Graph za přítele, a tak poskytuje Graph přístup ke svým soukromým polím.
Skutečnost, že si třída vybírá své vlastní přátele, znamená, že přátelství není obecně symetrické. V příkladu grafu nemá Vertex přístup k soukromým polím Graphu, ačkoli Graph má přístup k soukromým polím Vertexu.
Alternativy
Podobná, ale ne ekvivalentní, jazyková funkce je dána interním klíčovým slovem C #, které umožňuje třídám uvnitř stejné sestavy přístup k soukromým částem jiných tříd. To odpovídá označení každé třídy za přítele jiné ve stejné sestavě; třídy přátel jsou jemnější.
Programovací jazyky, které postrádají podporu tříd přátel nebo podobné jazykové funkce, budou muset implementovat alternativní řešení, aby dosáhly bezpečného rozhraní založeného na částech s datovou strukturou. Příklady takových zástupných řešení jsou:
- Zveřejněte pole dílů. Toto řešení snižuje zapouzdření tím, že umožňuje narušení invarianty datové struktury zvenčí.
- Přesuňte všechna proměnlivá strukturální data z části do datové struktury a zavádějte zpětný chod z každé části do její datové struktury. Toto řešení mění organizaci datové struktury a zvyšuje spotřebu paměti v případech, kdy by jinak tyto informace nebyly potřeba.
Vlastnosti
- Přátelství není symetrický - pokud třída
A
je přítel třídyB
, třídaB
není automaticky přítelem třídyA
. - Přátelství není tranzitivní - pokud třída
A
je přítel třídyB
a třídaB
je přítel třídyC
, třídaA
není automaticky přítelem třídyC
. - Přátelství není zdědil - pokud třída
Základna
je přítel třídyX
, podtřídaOdvozený
není automaticky přítelem třídyX
; a pokud třídaX
je přítel třídyZákladna
, třídaX
není automaticky přítelem podtřídyOdvozený
. Pokud však třídaY
je přítel podtřídyOdvozený
, třídaY
bude mít také přístup k chráněným částem třídyZákladna
, stejně jako podtřídaOdvozený
dělá.