 |
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
AFE-GmdG JLI MVP


Alter: 45 Anmeldedatum: 19.07.2002 Beiträge: 1374 Wohnort: Irgendwo im Universum... Medaillen: Keine
|
Verfasst am: 30.09.2004, 13:14 Titel: Zirkelbezüge |
|
|
Hab ich schonmal erwähnt, dass ich Zirkelbezüge hasse?
Ich habe derzeit 3 Klassen (es werden in naher Zukunft um die 30 sein!)
Klasse GUI - Hauptklasse, enthält aber eine GUIControl-Liste
Klasse GUIControl - Basisklasse für alle weiteren von Control abgeleiteten Klassen, enthält Verweis auf GUI sowie auf GUIContextMenu und eine GUIControl-Liste
Klasse GUIKontextMenu - Abgeleitete Klasse von GUIControl, enthält (durch die Basisklasse) Verweis auf GUI und eine GUIControl-Liste
Der Benutzer der Klassenbibliothek soll zum Schluss nur noch GUI.h einbinden müssen.
Ich komme jetzt mit den Headern arg in Bedrängnis:
Derzeit sieht GUI.h so aus (Wichtige Ausschnitte)
Code: |
#pragma once
[...]
class GUI; // Vorausdefinition der Klasse
#include "GUIContextMenu.h"
#include "GUIControl.h"
class GUI
{
[...]
private:
std::list<GUIControl*>* m_lpControls;
[...]
public:
void AddGUIControl(GUIControl* Control);
[...]
};
|
GUIControl.h (Wichtige Ausschnitte)
Code: |
#pragma once
// Vorausdefinition der Klasse, weil ein Pointer auf die Klasse schon in GUI.h
// verwendet wird.
class GUIControl;
#include "GUI.h"
#include "GUIContextMenu.h"
class GUIControl
{
[...]
protected:
GUIContextMenu* m_ContextMenu; // Enthält das Kontextmenu des Controls
std::list<GUIControl*>* m_lpControls; // Enthält alle ChildControls
[...]
public:
void AddGUIControl(GUIControl* Control);
[...]
};
|
und GUIContextMenu.h (Wichtige Ausschnitte)
Code: |
#pragma once
class GUIContextMenu; //Vorausdefinition der Klasse...
#include "GUIControl.h"
class GUIContextMenu : public GUIControl
{
[...]
};
|
Wie man (hoffentlich) erkennen kann, ist irgendwie jede Klasse mit jeder anderen Verbunden. Für die Vererbung gilt aber, dass bereits die vollständige Basisklasse bekannt ist - eine Vorausdefinition reicht nicht aus.
Kompelier ich mal die einzelnen Klassen in Gedanken bzw. "von Hand":
Code: |
GUI.cpp
#include GUI.h
Definition class GUI
#include GUIContextMenu.h
Definition class GUIContextMenu;
#include GUIControl.h
Definition class GUIControl;
#include GUI.h - wird geblockt
#include GUIContextMenu.h - wird geblockt
Fertigstellung class GUIControl {[...]};
Dabei werden Pointer auf GUI und GUIContextMenu benötigt - Alles Klar
Fertigstellung class GUIContextMenu{[...]} mit Referenz auf Basisklasse - Alles Klar
#include GUIControl - wird geblockt
Fertigstellung class GUI {[...]}
Dabei werden Pointer auf GUIControl verwendet - alles Klar
Fertig - alles Klar
GUIControl.cpp
#include GUIControl.h
Definition class GUIControl;
#include GUI.h
Definition class GUI;
#include GUIContextMenu.h
Definition class GUIContextMenu;
#include GUIControl.h - wird geblockt
Fertigstellung class GUIContextMenu : public GUIControl - CRASH GUIControl nicht fertiggestellt!
GUIContextMenu.cpp
#include GUIContextMenu.h
Definition class GUIContextMenu;
#include GUICOntrol.h
Definition class GUIControl;
#include GUI.h
Definition class GUI;
#include GUIContextMenu.h - wird geblockt
#include GUIControl.h - wird geblockt
Fertigstellung class GUI {[...]}
Dabei werden Pointer auf GUIControl verwendet - alles Klar
#include GUIContextMenu.h - wird geblockt
Fertigstellung class GUIControl {[...]}
Dabei werden Pointer auf GUI und GUIContextMenu benötigt - Alles klar
Fertigstellung class GUIContextMenu : public GUIControl - GUIControl fertiggestellt - Alles klar
Fertig - alles klar
|
Das ganze sieht jetzt zwar nur nach einem Fehler aus, aber wenn ich die Reihnfolge umändere wird es meisstens nur schlimmer.
Hab ich schonmal erwähnt, dass ich Zirkelbezüge hasse?
Wie kann ich das besser (sauber) lösen, ohne dass ich 3 verschiedene Versionen ein und desselben Header
brauche?
PS.: Diese Frage ist ernstgemeint! _________________
CPP: | float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;} |
|
|
Nach oben |
|
 |
TheMillenium Dark JLI'ler
Anmeldedatum: 21.07.2002 Beiträge: 1427 Wohnort: World Medaillen: Keine
|
Verfasst am: 30.09.2004, 13:21 Titel: |
|
|
könntest du das mal ins CVS laden? Will mal was ausprobieren... _________________ The source of all power is in its destiny... |
|
Nach oben |
|
 |
AFE-GmdG JLI MVP


Alter: 45 Anmeldedatum: 19.07.2002 Beiträge: 1374 Wohnort: Irgendwo im Universum... Medaillen: Keine
|
Verfasst am: 05.10.2004, 02:54 Titel: |
|
|
Ich glaube, ich hab eine Idee, wie ich das Problem umgehen kann. Leider muss ich dafür die Aufteilung "Jede Klasse eine Cpp-Datei und ein Header" aufgeben. Wenn ich nämlich die Aufteilung "Jede Klasse eine Cpp-Datei und ein Globaler Header" mache, kann ich die Zirkelbezüge umgehen, da nicht so viele ineinander verschlungene Includekommandos auftreten.
Ich bin immernoch für eine Bessere Lösung offen, weil grob gesagt gefällt mir das "ich klatsche alles in einen Header" nicht sonderlich gefällt... _________________
CPP: | float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;} |
|
|
Nach oben |
|
 |
xardias JLI Master

Alter: 38 Anmeldedatum: 28.12.2003 Beiträge: 804 Wohnort: Palo Alto, CA Medaillen: Keine
|
Verfasst am: 05.10.2004, 07:04 Titel: |
|
|
naja viel ändern sollte das nicht. ob du die header mit includes zusammen packst oder mit copy'n'paste in einen header packst. das ist doch schnuppe.
Aber es ist auch schwierig ein einen pointer auf eine child klasse zu speichern. das sollte sich eigentlich anders lösen lassen.
Also ich würde das Contect Menü nicht von GUIControl ableiten. Das ist nicht ganz richtig, oder hat ein kontextMenü ein KontextMenü ?
Vielleicht eher so:
Code: |
class GUIobject{ std::list<GUIObject*> mChilds; }
class GUI{...}
class GUIKontextMenu: public GUIObject;
class GUIControl: public GUIObject { GUIContextMenu* mContextMenu; }
|
so kannst du in der klasse GUI auf das Interface GUIObject zugreifen, welches du vor der class GUI deklarierst. und im anschluss daran kannst du dann die GUICOntrols, KontextMenüs usw machen.
Zirkelbezüge würd eich immer als Fehler im Design ansehen, meistens lassen sie sich umgehen. |
|
Nach oben |
|
 |
AFE-GmdG JLI MVP


Alter: 45 Anmeldedatum: 19.07.2002 Beiträge: 1374 Wohnort: Irgendwo im Universum... Medaillen: Keine
|
Verfasst am: 05.10.2004, 12:18 Titel: |
|
|
xardias hat Folgendes geschrieben: | naja viel ändern sollte das nicht. ob du die header mit includes zusammen packst oder mit copy'n'paste in einen header packst. das ist doch schnuppe. | Naja nicht ganz. Wenn die Klassen in mehreren Headern aufgeteilt sind, können durch unterschiedliche Includereihnfolgen oben genannte Fehler auftreten. Wenn alles in einer Datei ist (oder in Mehreren, aber dann werden die Dateien durch includes nur aneinandergehängt - sprich das Include kommt nur am Headerende) kann das so nicht passieren.
xardias hat Folgendes geschrieben: | Aber es ist auch schwierig ein einen pointer auf eine child klasse zu speichern. | Was soll daran schwierig sein?
xardias hat Folgendes geschrieben: | Zirkelbezüge würd eich immer als Fehler im Design ansehen, meistens lassen sie sich umgehen. | Wenn es geht, mach ich das auch, aber manchmal sind sie eben doch nicht umgehbar - und das wird umso häufiger, je komplexer ein Programm wird - und die GUI-Lib ist komplex _________________
CPP: | float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;} |
|
|
Nach oben |
|
 |
Kampfhund Super JLI'ler
Alter: 42 Anmeldedatum: 20.07.2002 Beiträge: 408
Medaillen: Keine
|
Verfasst am: 05.10.2004, 12:53 Titel: |
|
|
Du könntest sonst einfach das include "GUIContextMenu.h" in der GUIControl.h ans Ende des Headers setzen...denke ich.
EDIT: Ne, hab da was übersehen.
EDIT2: Ich mache vorausdefinitionen immer in der Datei, in der die vorausdefinition von nöten ist und nicht in der Headerdatei in der diese Klasse definiert ist. Hat das einen Nachteil/ist das falsch? Jedenfalls würde es so funktionieren (wenn ich keinen Fehler gemacht habe). _________________ Kochen ist ein NP-schweres Optimierungsproblem. |
|
Nach oben |
|
 |
AFE-GmdG JLI MVP


Alter: 45 Anmeldedatum: 19.07.2002 Beiträge: 1374 Wohnort: Irgendwo im Universum... Medaillen: Keine
|
Verfasst am: 05.10.2004, 17:08 Titel: |
|
|
Ich hab im Header die Zeile GUIControl* oder GUIContextMenu* usw. verwendet. daher benötige ich die vorausdefinitionen schon im Header.
Ich könnte natürlich auch alles void* machen, aber sowas find ich wieder scheisse. Das Urspruingsproblem ist durch eine Reorganisierung aller Header inzwischen aus der Welt geschafft. _________________
CPP: | float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;} |
|
|
Nach oben |
|
 |
Kampfhund Super JLI'ler
Alter: 42 Anmeldedatum: 20.07.2002 Beiträge: 408
Medaillen: Keine
|
Verfasst am: 05.10.2004, 20:56 Titel: |
|
|
Ich meinte es ungefähr so:
Bsp:
GUIControl.h
Code: |
class GUIContextMenu; // hier steht meine vorausdefinition, nicht in GUIContextMenu.h
class GUIControl
{
GUIContextMenu *pMenu;
}
#include "GUIContextMenu.h" // diese Zeile könnte man wohl auch in die .cpp verschieben
|
_________________ Kochen ist ein NP-schweres Optimierungsproblem. |
|
Nach oben |
|
 |
xardias JLI Master

Alter: 38 Anmeldedatum: 28.12.2003 Beiträge: 804 Wohnort: Palo Alto, CA Medaillen: Keine
|
Verfasst am: 06.10.2004, 09:00 Titel: |
|
|
Sicher umgehen lassen sie sich nicht immer, aber wie steht es denn mit dem Lösungsvorschlag von mri oben ? damit sollte der Zirkelbezug doch eigentlich aufgehoben sein, oder sehe ich das falsch ? |
|
Nach oben |
|
 |
AFE-GmdG JLI MVP


Alter: 45 Anmeldedatum: 19.07.2002 Beiträge: 1374 Wohnort: Irgendwo im Universum... Medaillen: Keine
|
Verfasst am: 06.10.2004, 15:39 Titel: |
|
|
Ich hab wie gesagt eine Lösung durch Erneuerung des Includeverhaltens erreicht. In wieweit die Lösung mit deiner übereinstimmt, weiss ich nicht 100%ig - ich hab auch keine wirkliche Lust, extra nochmal umzustellen, damit ich deine Variante testen kann.
Für mich war ja (in diesen speziellen Fall) das Ergebnis wichtiger, als der Weg dahin.
Trotzdem bedanke ich mich natürlich für deine Mühe - vielleicht kann ich ja auch mal wieder helfen ;-P _________________
CPP: | float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;} |
|
|
Nach oben |
|
 |
xardias JLI Master

Alter: 38 Anmeldedatum: 28.12.2003 Beiträge: 804 Wohnort: Palo Alto, CA Medaillen: Keine
|
Verfasst am: 06.10.2004, 17:08 Titel: |
|
|
ich dachte ja nur dass du die zirkelbezüge Weg haben wolltest...
aber so lang es funktioneirt  |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|