Używanie klas „zaprzyjaźnionych” w tworzeniu gier

9

Zazwyczaj w C ++ szybkość tworzenia gier jest ceniona nad enkapsulacją, dlatego widzimy masę publicznie dostępnych członków klasy, którzy tak naprawdę nie powinni być publiczni.

Wydaje mi się, że w większości przypadków tylko kilka bardzo wybranych klauzul naprawdę musi znać wewnętrzne działanie innych klas do tego stopnia, że ​​modyfikuje lub odczytuje ich prywatne dane.

Tworzenie publicznych programów pobierających / ustawiających dla tych prywatnych danych ujawnia rzeczy, których tak naprawdę nie należy modyfikować bezmyślnie.

Czy kompromisem byłoby tutaj wykorzystanie klas przyjaciół? czy jest jakaś wada w stosunku do klas znajomych, których nie widzę.

David Young
źródło

Odpowiedzi:

8

Zajęcia towarzyskie mają dwie główne wady.

  1. Nie możesz wybrać, co chcesz udostępnić znajomym. To wszystko albo nic. Może to okazać się problematyczne, jeśli próbujesz wymusić obowiązkowe użycie jakiegoś nieistotnego setera.
  2. Wasze dwie klasy są teraz nieco połączone w tym sensie, że przyjaciel wie o przyjacielu.

To powiedziawszy, użycie klas znajomych może zdecydowanie poprawić enkapsulację, szczególnie jeśli alternatywą są publiczne programy pobierające / ustawiające.

Również powiązane pytanie dotyczące SO: /programming/521754/when-to-use-friend-class-in-c

Tetrad
źródło
5

Kapsułkowanie jest przyjemne, ale rozdzielenie problemów jest przyjemniejsze.

Klasa uzyskująca dostęp do „części prywatnej” innej klasy może wskazywać, że kod nie jest dobrze zaprojektowany.

Za każdym razem, gdy znajdziesz się w „Boże, muszę stworzyć tutaj klasę przyjaciela”, pytanie, które powinieneś sobie zadać, brzmi: „Czy robię to poprawnie, czy jest to czystszy sposób?” (alias „Czy to mnie później ugryzie w tyłek?”).

Jeśli masz pewność co do „życzliwości”, umieść ją tam bez wahania.

egarcia
źródło
Rozumiem, jak korzystanie z klasy przyjaciela ściśle łączy jedną klasę z drugą. Zastanawiałem się, czy istnieje jakiś wzorzec projektowy, który łagodzi ten problem, ponieważ samo owinięcie czegoś w getter / setter jest potencjalnie gorszym rozwiązaniem.
David Young
1
Ciekawym przykładem jest wzorzec Factory w C ++ wymaga „przyjaciela” ze względu na użycie prywatnych konstruktorów.
David Young
2

Inną opcją jest użycie idiomu PIMPL , w którym częścią implementacji struktury jest wskaźnik do innego typu. Większość użytkowników klasy po prostu dołącza zwykły plik nagłówka, w którym implementacja jest nieprzezroczystym wskaźnikiem. Klasy, które potrzebują dostępu do danych prywatnych, mogą zawierać nagłówek określający inny typ i korzystać z interfejsu, który udostępnia.

Jest to powszechny wzorzec dla programistów C chcących funkcji podobnych do znajomych. Moim zdaniem bardziej skupia się na myśleniu o oddzieleniu problemów (ogólnie dobra zasada projektowania, która prowadzi do wielokrotnego użytku, ortogonalnego kodu) zamiast enkapsulacji (technika specyficzna dla OO, która jest przydatna do implementacji separacji problemów, ale także często nadużywana nadmiernie komplikować rzeczy).

Ma tę przewagę nad przyjacielem, że w ogóle nie łączy przyjaciela z przyjacielem. Niektórzy ludzie mogą twierdzić, że jest to wada, ponieważ teraz każdy może „zaprzyjaźnić się” z twoją klasą. Myślę, że to nieuzasadniony strach, ponieważ nadal wyraźnie określasz związek (włączając nagłówek). Jeśli się tego obawiasz, boisz się swojej (lub współpracownika) zdolności do podejmowania mądrych decyzji architektonicznych. Ale jeśli później nie możesz właściwie podjąć tych decyzji, to czemu ufasz friendteraz?

Ma to wadę kosztu działania. Przechowując dane we wskaźniku, masz gorszą spójność pamięci podręcznej i większą liczbę alokacji, a także potrzebujesz niszczyciela, aby je wyczyścić.


źródło
+1 interesujące, nie słyszałem o tej koncepcji pochodzącej z Java.
David Young