Wie "Sichtbarkeit der Klasse" (nicht von Funktionen) in C ++ gefälscht?

8

Es gibt keine Funktion, die Sichtbarkeit / Zugänglichkeit der Klasse in C ++ kontrolliert .

Gibt es eine Möglichkeit, es zu fälschen?
Gibt es irgendein Makro / Template / Magie von C ++, das das nächste Verhalten simulieren kann?

Hier ist die Situation

Util.h (Bibliothek)

%Vor%

B.h (Bibliothek)

%Vor%

C.h (Bibliothek)

%Vor%

D.h (Benutzer)

%Vor%

Meine arme Lösung

Erzeuge alle Mitglieder von Util als privat und deklariere dann: -

%Vor%

( Bearbeiten: Vielen Dank A.S.H für "keine Vorwärtsdeklaration erforderlich".)

Nachteil: -

  • Es ist ein modifizierendes Util , um B und C irgendwie zu erkennen.
    Es macht meiner Meinung nach keinen Sinn.
  • Jetzt können B und C auf jedes Mitglied von Util zugreifen, brechen Sie% access_guard% access_guard ab Es gibt eine Möglichkeit, einen Freund nur für einige Mitglieder zu aktivieren Aber es ist nicht so süß und für diesen Fall unbrauchbar.
  • private kann D nicht verwenden, aber kann sie trotzdem sehen.
    Util ist immer noch eine Option, wenn Sie die automatische Vervollständigung verwenden (zB Strg + Leerzeichen ) in Util .

(Bearbeiten) Hinweis: Es dreht sich alles um Komfort beim Codieren; um einen Bug oder eine schlechte Verwendung zu verhindern / bessere Autovervollständigung / bessere Kapselung. Hier geht es nicht um Anti-Hacking oder um unbefugten Zugriff auf die Funktion zu verhindern.

(Bearbeiten, akzeptiert):

Leider kann ich nur eine Lösung akzeptieren, also habe ich diejenige ausgewählt, die weniger Arbeit erfordert und viel Flexibilität bietet.

Für zukünftige Leser: Preet Kukreti (& amp; texasbruce im Kommentar) und Shmuel H (& amp; ASH ) stark> ist Kommentar) hat auch gute Lösungen zur Verfügung gestellt, die es wert sind, gelesen zu werden.

    
javaLover 14.01.2017, 02:10
quelle

3 Antworten

3

Eine mögliche Lösung wäre, Util in einen Namespace und typedef it in die Klassen B und C zu schieben:

%Vor%

Wenn die Klasse Util in util.cpp implementiert ist, würde dies ein Wrapping in namespace util_namespace { ... } erfordern. Soweit B und C betroffen sind, kann sich ihre Implementierung auf eine Klasse mit dem Namen Util beziehen, und niemand würde dies wissen. Ohne die Aktivierung von typedef findet D keine Klasse mit diesem Namen.

    
Sam Varshavchik 14.01.2017, 02:23
quelle
5

Ich denke, dass der beste Weg ist, Util.h überhaupt nicht in einen öffentlichen Header aufzunehmen.

Um dies zu tun, #include "Util.h" nur in der Implementierung cpp file:

Lib.cpp :

%Vor%

Dadurch stellen Sie sicher, dass die Änderung von Util.h nur in Ihren Bibliotheksdateien und nicht in den Benutzern der Bibliothek einen Unterschied macht.

Das Problem bei diesem Ansatz ist, dass Util nicht in Ihren öffentlichen Headern ( A.h , B.h ) verwendet werden kann. Vorwärts-Deklaration könnte eine Teillösung für dieses Problem sein:

%Vor%     
Shmuel H. 14.01.2017 09:25
quelle
2

Eine Möglichkeit besteht darin, eine einzige Zwischenklasse anzusprechen, deren einziger Zweck es ist, eine Zugriffsschnittstelle für die zugrunde liegende Funktionalität bereitzustellen. Dies erfordert ein wenig Standard. Dann sind A und B Unterklassen und können daher die Zugriffsschnittstelle verwenden, aber nicht direkt in Utils :

%Vor%

Weder A noch B haben direkten Zugriff auf Util . Client-Code kann UtilAccess -Member auch nicht über A oder B -Instanzen aufrufen. Das Hinzufügen einer zusätzlichen Klasse C , die die aktuelle Util -Funktionalität verwendet, erfordert keine Änderung am Code Util oder UtilAccess .

Dies bedeutet, dass Sie eine bessere Kontrolle über Util haben (insbesondere wenn es zustandsbehaftet ist), um den Code leichter zu verstehen, da der Zugriff über eine vorgeschriebene Schnittstelle erfolgt, anstatt direkten / versehentlichen Zugriff auf anonymen Code zu gewähren A und B ).

Dies erfordert einen Textbaustein und propagiert nicht automatisch Änderungen von Util , jedoch ist es ein sichereres Muster als direkte Freundschaft.

Wenn Sie keine Unterklasse erstellen möchten und Sie UtilAccess für jede verwendende Klasse ändern möchten, können Sie die folgenden Änderungen vornehmen:

%Vor%

Es gibt auch einige verwandte Lösungen (für eine strengere Zugriffskontrolle auf Teile einer Klasse), eine namens Attorney-Client und die andere PassKey , auf die beide eingegangen sind diese Antwort: saubere C ++ granulare Freund gleichwertig? (Antwort: Attorney-Client Idiom) . Rückblickend denke ich, dass die Lösung, die ich vorgestellt habe, eine Variante des Attorney-Client-Idioms ist.

    
Preet Kukreti 14.01.2017 03:29
quelle