JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=e0b113b2ab104f3c92d33d66d0726013Medaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Zirkelbezüge

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 30.09.2004, 13:14    Titel: Zirkelbezüge Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
TheMillenium
Dark JLI'ler



Anmeldedatum: 21.07.2002
Beiträge: 1427
Wohnort: World
Medaillen: Keine

BeitragVerfasst am: 30.09.2004, 13:21    Titel: Antworten mit Zitat

könntest du das mal ins CVS laden? Will mal was ausprobieren...
_________________
The source of all power is in its destiny...
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 05.10.2004, 02:54    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
xardias
JLI Master


Alter: 38
Anmeldedatum: 28.12.2003
Beiträge: 804
Wohnort: Palo Alto, CA
Medaillen: Keine

BeitragVerfasst am: 05.10.2004, 07:04    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 05.10.2004, 12:18    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Kampfhund
Super JLI'ler


Alter: 42
Anmeldedatum: 20.07.2002
Beiträge: 408

Medaillen: Keine

BeitragVerfasst am: 05.10.2004, 12:53    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 05.10.2004, 17:08    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Kampfhund
Super JLI'ler


Alter: 42
Anmeldedatum: 20.07.2002
Beiträge: 408

Medaillen: Keine

BeitragVerfasst am: 05.10.2004, 20:56    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
xardias
JLI Master


Alter: 38
Anmeldedatum: 28.12.2003
Beiträge: 804
Wohnort: Palo Alto, CA
Medaillen: Keine

BeitragVerfasst am: 06.10.2004, 09:00    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 06.10.2004, 15:39    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
xardias
JLI Master


Alter: 38
Anmeldedatum: 28.12.2003
Beiträge: 804
Wohnort: Palo Alto, CA
Medaillen: Keine

BeitragVerfasst am: 06.10.2004, 17:08    Titel: Antworten mit Zitat

ich dachte ja nur dass du die zirkelbezüge Weg haben wolltest...
aber so lang es funktioneirt Wink
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
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

Impressum