2015-04-27 19 views
10

Ich habe eine Klasseninstanz, auf die einige andere Klassen zugreifen müssen.Alternativen zu statisch und global in C++?

  • Es wäre ziemlich umständlich, die Instanz immer über die Baukette zu führen.
  • Ich habe versucht, globale Variable zu vermeiden, da Leute dazu neigen, dagegen zu beraten.
  • Ich dachte, ich erkläre diese Instanz ein statisches Element einer Klasse und sind dann diese Klasse, um die Instanz zugreifen, aber das funktioniert nicht, entweder

error: calling a private constructor of class 'Foo'

Um das Problem weiter in die angeben Kontext des QGraphicsView Frameworks: Ich möchte QGraphicsItems hinzufügen, die von einer Controller-Klasse (die Elemente verwalten) zu QGraphicsScene hinzugefügt werden, was ein Mitglied meiner QMainWindow-Klasse ist (aber ich beharre nicht auf diesem Detail).

Ich verbringe viel Zeit mit der Suche im Internet, aber ich bin ziemlich neu und bin hier irgendwie festgefahren. Ich schätze jeden Anreiz dafür, wie der beste Weg zur Lösung des Dilemmas wäre.

+5

statisch in einer Klasse hat einige Nachteile mit globalen Variablen. Das sauberste Ding ist der "umständliche" Parameter-Passing – deviantfan

+3

Sie sollten sich über das Singleton-Muster informieren: http://en.wikipedia.org/wiki/Singleton_pattern – Caduchon

+4

@Caduchon ... außer Singletons sind aus den gleichen Gründen nicht beliebt (Immerhin, das übliche Singleton basiert auf statischen Klassenvariablen). Einige lesen: http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons etc.etc. – deviantfan

Antwort

0

Dieses Problem tritt auf, wenn Sie einen Entwurf haben, wo Klasse A Klasse erstellt B die C Klasse erstellt, das eine Instanz der Klasse muss D in seinem Konstruktor akzeptieren. Dann müssen Sie D den ganzen Weg durch A, B und C übergeben. Wenn Sie den Entwurf so ändern, dass er eine Funktion zum Erstellen von Instanzen hat (entweder in der Hauptklasse oder in einer Fabrikklasse), die weiß, wie Sie A, B, C und erstellen können. Dann können Sie diese Funktion wie folgt schreiben:

D d; 
C c(d); 
B b(c); 
A a(b); 

Auf diese Weise akzeptiert jede Klasse nur ihre Abhängigkeiten.

Wenn Sie später erkennen, dass B muss auch Klasse verwenden D dann können Sie nur den Konstruktor von B ändern, ohne den Konstruktor von A zu beeinflussen.

+0

Also dann a-> b-> c-> d-> etwas (a); ? Was ist der Unterschied zwischen dieser und immer den Zeiger auf den gleichen Wert? D d; Cc (d); B b (d); A a (d); – TheMindWithin

+1

Wer ruft an, was? Die Klasse, die sie aufruft, sollte ein D und nicht ein A enthalten. –

+0

Angenommen, A wäre das zu QGraphicsScene D hinzuzufügende GraphicsItem, würde es so aussehen: a-> d-> addItem (a); Oder habe ich dein Beispiel missverstanden? – TheMindWithin

2

Die Verwendung von Globalen wird sehr kontrovers diskutiert, deshalb möchte ich darauf hinweisen, dass das, was ich im Folgenden schreibe, meine persönliche Meinung ist und offen für Diskussionen ist.

Ich weiß keine Möglichkeit neben der Übergabe von Instanz, um Ihr Problem ohne ein globales Objekt zu lösen. Ich persönlich glaube nicht, dass eine globale Instanz in jeder Situation eine böse Sache ist.

  1. Wenn ich eine Bibliothek, die ich globale Objekte außer einer Fabrik zu vermeiden, neigen zu entwerfen. Globale Objekte werden oft als Abkürzung verwendet, wenn keine Verknüpfung benötigt wird oder um ein Tippen für den Programmierer zu vermeiden. Außerdem sollten die meisten Klassen in einer Bibliothek unabhängig sein. Sie opfern Unabhängigkeit, wenn Sie globale Instanzen in solchen Klassen verwenden.

  2. Wenn ich Statik in einer Klasse verwende, verwende ich sie nur, wenn die gesamte Klasse ein Singleton ist oder für Factory-Methoden (z. B. erstellen oder erhalten). Niemals so, wie du es beschrieben hast. In der Art, wie Sie es beschrieben haben, ist es für andere Entwickler unerwartet, da Sie eine dritte Partei benötigen, um dieses statische Objekt zu initialisieren. Sie erhalten damit nichts, außer dass Sie einen längeren Konstruktor eingeben müssen. Dies kann kein Ziel sein.

  3. Wenn ich eine globale Instanz verwende, wickle ich sie immer in eine Verwaltungsklasse. Ich verwende niemals Klassen von Drittanbietern wie QGraphicsItems direkt als globale Variablen (auch keine "primitiven" Klassen oder Typen). Wie in Punkt 2 können andere dies nicht als global erwarten. Wichtiger ist es nicht, wer die Instanz zu füllen oder zu töten hat. Ein "GraphicsItemManager" kann eine "setup" -Methode haben, die das für dritte Benutzer völlig klar macht.

  4. Passing Instanzen ist nicht in jeder Situation der beste Weg IMHO. Nicht alle meine Klassen sind für die Wiederverwendung, sie sind nur für ein Projekt. Hier ist die Geschwindigkeit der Realisierung, die Benutzerfreundlichkeit und die klare Gruppierung mehr wert als ein Dogma als "no globals". Die meiste Zeit schreibe ich Manager-Klassen, die Instanzen von z. grafische Elemente. Ich habe nicht das Gefühl, dass der Code weniger lesbar wird, solange ich die Regeln verwende, auf die ich zuvor hingewiesen habe.

  5. Manchmal ist eine Ressource nicht zur Verfügung, so dass Sie bereits einen Wrapper übergeben haben. Dies führt zu einem Punkt, an dem Instanzen durch Klassen übergeben werden, die selbst diese Ressource nicht benötigen oder selbst Teil einer Bibliothek sind (in diesem Fall können Sie den Konstruktor oft nicht ändern). Dies kann (wie wir alle Menschen sind) zu Fehlinterpretationen führen. Ich benutze globale Management-Klassen, um über diese "gabs" zu springen, da ich denke, dass es mehr Wert ist, diesen Raum sauber von Abhängigkeiten zu halten.

Wie ich schrieb IMHO.