friend-Klasse für nur bestimmte Funktionen
-
Ist es eigentlich möglich, dass man in einer Klasse deklarieren kann, dass eine andere Klasse als friend-Klasse gilt, die jedoch nur auf bestimmte Funktionen von der ersten Klasse zugreifen kann? Also so nach dem Motto: Klasse A erlaubt Klasse B, auf die private Funktion A::F() zuzugreifen. Alle weiteren privaten Funktionen von Klasse A sind für Klasse B nach wie vor nicht zugreifbar.
-
Nein.
-
Wozu brauchst du das?
-
EOutOfResources schrieb:
Wozu brauchst du das?
Die Kapselung wird erhöht, wenn der Zugriff stärker eingeschränkt ist. Sollte eigentlich klar sein...
-
Nexus schrieb:
Die Kapselung wird erhöht, wenn der Zugriff stärker eingeschränkt ist.
Ich meinte eigentlich das konkrete Problem. Nicht wozu man diese Vorgehensweise nutzt.
-
Es geht konkret um eine Art und Weise, ein Spiel zu programmieren: Ich habe eine Sprite-Klasse und eine Screen-Klasse. Und das Sprite muss natürlich irgendwie auf den Screen gezeichnet werden. Stellen wir uns mal vor, das ganze wird mit dem Windows GDI implementiert. Dann würde die Sprite-Klasse ein HBITMAP als private Variable haben und die Screen-Klasse hätte ein HWND. Zum Zeichnen erstellt man dann lokal von beidem einen HDC und benutzt BitBlt. Aber egal, wie man es dreht und wendet: Eine Klasse braucht Zugriff auf den privaten Member der anderen:
Sprite::DrawToScreen(const Screen &screen) --> Sprite muss auf das HWND zugreifen können Screen::DrawSprite(const Sprite &sprite) --> Screen muss auf das HBITMAP zugreifen könnenUnd eine öffentliche Funktion Sprite::GetHBitmap() möchte ich nicht machen, da ich das Interface plattform- und implementierungsunabhängig halten will. Wenn ich zum Beispiel auf DirectX wechsle, gibt es ja statt HWND und HBITMAP irgendwelche DirectX-Surfaces. Und solche spezifischen Dinge soll es nur in den CPP-Daeien geben und als private Variablen. Aber alles, was public oder protected ist, soll auch absolut unabhängig sein und soll nur das benutzen, was das reine Standard-C++ zur Verfügung stellt.
-
Edit: Die eine Funktion
Sprite::DrawToScreen(const Screen &screen)muss natürlich so hier aussehen:
Sprite::DrawToScreen(Screen &screen)
-
Man kann das was du willst über eine Zwischenklasse erreichen:
class foo { private: friend class foo_access; void a(); void b(); }; class foo_access { private: friend class bar; static void do_a(foo& f) { f.a(); } }; class bar { public: void c(foo& f) { foo_access::do_a(f); } };bar kann jetzt (indirekt) foo::a verwenden, aber nicht foo::b.
Wobei ich das nur in echten "Notfällen" empfehlen würde.
ps: in deinem speziellen Fall würde ich entweder
a) das HWND über einen ganz normalen öffentlichen Getter zur Verfügung stellen oder
b) der Screen Klasse eine public BitBlt Funktion verpassen, so dass das HWND nicht "herausgegeben" werden muss oder
c) eine der beiden Klassen zum Friend des anderen machenBei solchen Dingen hast du sowieso immer eine starke Koppelung zwischen Klassen, das lässt sich nicht vermeiden.
Und der User-Programmer kann ja die "friend" Stellung von z.B. Sprite nicht "ausnutzen", indem er von Sprite ableitet: seine abgeleitete Klasse ist ja kein friend mehr.Bzw. statt "Sprite" sollte die Klasse die "sich" auf den "Screen" zeichnen kann vielleicht eine Ebene tiefer angesiedelt werden: eine "Image" Klasse, die einfach nur ein Bild kapselt. Die Sprite Klasse kann dann von der "Image" Klasse gebrauch machen, um etwas auf den Schirm zu zeichnen.
Viele Wege führen nach Rom. Das oben gezeigte ("friend" über Umwegen) würde ich in so einem Fall nicht verwenden. Ist unnötig kompliziert und verwirrt nur.
-
Schandmund schrieb:
Ist es eigentlich möglich, dass man in einer Klasse deklarieren kann, dass eine andere Klasse als friend-Klasse gilt, die jedoch nur auf bestimmte Funktionen von der ersten Klasse zugreifen kann? Also so nach dem Motto: Klasse A erlaubt Klasse B, auf die private Funktion A::F() zuzugreifen. Alle weiteren privaten Funktionen von Klasse A sind für Klasse B nach wie vor nicht zugreifbar.
Es geht aber anderstrum. Ist jetzt vermutlich nicht unbedingt die Lösung für
dein Problem, aber vielleicht kanntest du ja diese Möglichkeit noch nicht://-------------------------------------------------------------------- // Diese Klasse ruft eine private Funktion auf //------------------------------------------------------------ class CIchBinDeinFreund { public: void PrivateFunktionAufrufen( CWerWillMeinFrundSein* a_pFreund ); }; //------------------------------------------------------------ // Die private Funktion dieser Klasse soll aufgerufen werden //------------------------------------------------------------ class CWerWillMeinFrundSein { private: friend void CIchBinDeinFreund::PrivateFunktionAufrufen( CWerWillMeinFrundSein* a_pFreund ); void AusgabeIrgendwas(); }; //------------------------------------------------------------ // Funktionen definieren //------------------------------------------------------------ void CIchBinDeinFreund::PrivateFunktionAufrufen( CWerWillMeinFrundSein* a_pFreund ) { a_pFreund->AusgabeIrgendwas(); } void CWerWillMeinFrundSein::AusgabeIrgendwas() { // hier irgendwas machen } //------------------------------------------------------------ // Aufruf der privaten Funktion im Quellcode... //------------------------------------------------------------ CWerWillMeinFrundSein DrueckMich; CIchBinDeinFreund Freund; Freund.PrivateFunktionAufrufen( &DrueckMich );Gruß Ulli
-
Ein weiterer Trick wäre die Verwendung des Handle Body Idioms, nur in diesem Fall nicht zur Auslagerung von Daten, sondern auch privaten Methoden.