• Diese Seite verwendet Cookies. Indem du diese Website weiterhin nutzt, erklärst du dich mit der Verwendung von Cookies einverstanden. Erfahre mehr

Abhängigkeit zwischen zwei Klassen (c++)

soul_rebel

ist immer auf der flucht
Themenstarter #1
Also ich habe eine klasse MyObject und eine dazugehörige SingletonKlasse MyObjectGlobal. Objekte vom Typ MyObject haben einen statischen Pointer auf ein Objekt vom Typ MyObjectGlobal.

So weit so gut, das hat früher immer funtkioniert. Jetzt habe ich als Teil von Neuschreib und Aufräumarbeiten MyObjectGlobal seine eigene Datei gegeben. Das klappt aber irgendwie nicht, denn schließlich muss MyObject MyObjectGlobal "includen", umgekehrt aber auch :zitter:
Tja und das ist eine zirkuläre Abhängigkeit die irgendwie schlecht ist besonder da die Compileranweisungen natürlich das einbinden von "myobject.h" durch MyObjectGlobal so einer Null-Datei machen.

Kann man das irgendwie sauber lösen oder sollte ich MyObjectGlobal wieder in dieselbe Datei packen wie MyObject?

Thx
 

hippodriver

Well-Known Member
#2
Wie wäre es mit einer Vorwärtsdeklaration? Damit löst man zirkuläre Abhängigkeiten.
Ein "class MyObjectGlobal;" in MyObject.cpp oder umgekehrt könnte funktionieren.
Ich "liebe" C++.

MfG
Michael Krauß
 

qfat

Well-Known Member
#3
der einfachste und sauberste weg (meine meinung) so etwas zu umgehen ist nen interface (abtrakte klasse)

also das singleton hat ja keinen konstruktor sondern ne factory methode.
der rest sollte ja identisch sein (weiß nicht was du sonst noch so gemacht hast)

also einfach ne abstrakte klasse definieren die alle methoden definiert und fertig isses.

dann haste das ring include aufgelöst und kannst rum casten.
 

soul_rebel

ist immer auf der flucht
Themenstarter #4
Wie wäre es mit einer Vorwärtsdeklaration? Damit löst man zirkuläre Abhängigkeiten.
Ein "class MyObjectGlobal;" in MyObject.cpp oder umgekehrt könnte funktionieren.
Das hatte ich auch schon ausprobiert. Klappt aber nicht, das gibt in der jeweiligen Klasse dann ein
Code:
error: invalid use of undefined type 'MyObjectGlobal'
error: forward declaration of 'MyObjectGlobal'
@qfat: ne ein interface geht nicht. MyObjectGlobal soll schon ein richtiges Objekt mit Member und Memberfunktionen sein (und hat auch einen Konstruktor).
 

qfat

Well-Known Member
#5
na klar geht interface :) das geht immer

dein objekt ist ja nen richtiges objekt mit allem drum und dran!
nur eben programmierst du gegen das interface.

also verstehe jetzt dein problem daran nicht
 

Kamikaze

Warrior of Sunlight
#6
Ich hatte mal das gleiche Problem, ein Prototyp war die Lösung.

In MyObject:
Code:
class MyObjectGlobal;
Der Prototyp gehört direkt nach die Includes.

Denk dran, das im gleichen Namespace zu machen. In MyObjectGlobal kannst du das Include lassen.
 

xbit

Well-Known Member
#7
Das hatte ich auch schon ausprobiert. Klappt aber nicht, das gibt in der jeweiligen Klasse dann ein
Code:
error: invalid use of undefined type 'MyObjectGlobal'
error: forward declaration of 'MyObjectGlobal'
Wie sieht Deine Forward Deklaration denn aus? ;)

Eigentlich sollte es ausreichen, wenn Du in dem Header zu MyObject vor die Klassendefinition von MyObject die Forware Deklaration von MyObjectGlobal schreibst. Da Du in MyObject ja nur 'nen Pointer verwendest, sollte das kein Problem sein.

HTH
 

mike

Well-Known Member
#8
Wenn du nen Header Guard hast - check mal ob du irrtümlich 2 Mal den gleichen hast. MS VS Studio streicht das an - aber sonst kenn ich keine IDE die das checkt
 

soul_rebel

ist immer auf der flucht
Themenstarter #9
Da Du in MyObject ja nur 'nen Pointer verwendest, sollte das kein Problem sein.
Naja ich rufe schon Member-funktionen von MyObjectGlobal auf. Also ein global->foobar();

Wie sieht Deine Forward Deklaration denn aus? ;)
myobject.h hat gesagt.:
#ifndef __MYOBJECT_H__
#define __MYOBJECT_H__

// normale includes

class MyObjectGlobal;

// Klassendeklaration von MyObject
// darin enthalten ein static MyObjectGlobal* global;
#endif
myobjectglobal.h hat gesagt.:
#ifndef __MYOBJECTGLOBAL_H__
#define __MYOBJECTGLOBAL_H__

#include "myobject.h"

//Klassendeklaration von MyObjectGlobal

#endif
myobject.cpp hat gesagt.:
#include "myobject.h"
//Implementierung der Memberfunktionen
myobjectglobal.cpp hat gesagt.:
#include "myobjectglobal.h"
//Implementierung der Memberfunktionen
 

xbit

Well-Known Member
#10
Naja ich rufe schon Member-funktionen von MyObjectGlobal auf. Also ein global->foobar();
Hatte ich auch erwartet. ;) Forward Deklarationen funktionieren aber nur, wenn man Pointer oder Referenzen verwendet, weil der Compiler dafuer die exakte Groesse der Klasse nicht kennen muss. Im Prinzip kannst Du jede Klasse, die nur ueber Pointer referenzierst, per Forward Deklaration im Header einbinden.

OK, zu Deinem Problem: Ich vermute, dass Du myobjectglobal.h nicht einbindest. Dies ist aber notwendig, um damit zu arbeiten. Die Forward Deklaration dient nur dem Aufloesen der zyklischen Abhaengigkeit, aber spaetestens in myobject.cpp muss der Header von myobjectglobal eingebunden werden. Anhand Deiner Codeschnippsel vermute ich, dass hier das Problem liegt.

HTH
 

mike

Well-Known Member
#11
Wenn man einen Pointer auf eine Klasse X benutzt - warum sollte man da mehr als nur eine Vorwärtsdeklaration brauchen? Ein Pointer ist immer gleich groß ...
Schreibst du vor der Verwendung in einer CPP explizit hin dass das Ding existiert?
z.B.: MyObjectGlobal* MyObject::global;
Die Fehlermeldung ist da im Regelfall anderes - aber man weiß ja nie ;)
Ansonsten poste mal mehr


mfg
 

oenone

Well-Known Member
#12
Zeig mal mehr Code, die Kristallkugel sagt mir leider nicht mehr.

Zirkuläre Abhängigkeiten sind meistens ein Zeichen von schlechtem Design....

auf bald
oenone
 

soul_rebel

ist immer auf der flucht
Themenstarter #13
Danke xbit, das Einfügen von #include "myobjectglobal.h" in die myobject.cpp hat jetzt erst mal Abhilfe geschaffen.

oenone hat gesagt.:
Zirkuläre Abhängigkeiten sind meistens ein Zeichen von schlechtem Design....
Ja ich weiß, aber Tausende Funktionen und member statisch machen ist noch schlechteres....
 

Amin

Well-Known Member
#14
Hat ja nichts mit statisch machen zu tun.
Lies dir mal gute Literatur zu OO-Design durch. Statisch hat damit nichts zu tun. Sondern eher mit Interfaces zu arbeiten. Interfaces kannst du in C++ durch abstrakte Klassen abbilden. Z.B. können lokale Klassen Wunder bewirken. Auch die Aufteilung in mehrere Projekte/Libs kann Abhängigkeiten minimieren.
 

Kamikaze

Warrior of Sunlight
#15
Ich finde zirkuläre Dependencies sind vollkommen Normal, wenn es um Listen, Bäume und Netze geht.

Vielleicht ist dein Compileraufruf auch falsch. Du darfst dem Compiler keine Headerdateien übergeben.
 

xbit

Well-Known Member
#16
Soweit ich das verstanden habe, laeuft es nun und es lag daran, dass er das EInbinden der Header Files durch die Fordward Deklarationen ersetzt hat, was jedoch nicht funktioniert.

Ansonsten sehe auch keinen schwerwiegenden Fehler darin, zirkulaere Abhaengigkeiten zu haben.