# [C++]sind zwei Klassen, die gegenseitig aufeinander zugreifen möglich?



## Suehprom (18. Februar 2004)

Hallo Leute,
ich hab ein riesen Problem und suche schon seid Tagen in Foren und Chats nach einer Lösung.

Ich möchte zwei Klassen schreiben, die Daten unterander austauschen können. D.h. eine erste Klasse "KlassA" soll auf Methoden einer zweiten Klasse "KlasseB" Zugriff haben und umgekehrt.
Mein Ansatz dazu war folgender:

*
class KlasseB;  // KlasseB wird bekannt gemacht

class KlasseA{
  public:
    KlasseA();      //Konstruktor
    ~KlasseA();    //Destruktor

    KlasseB* p;       // Zeiger vom Typ KlasseB
    void func_a();
    void set_p(KlasseB* kl); //Methode setzt Zeiger auf eine Instanz des Typs "KlasseB"
    ...
  private:
    ...  
};

void KlasseA::set_p(KlasseB* kl){
  p = kl;
}
...

class KlasseB{
  public:
    KlasseB();      //Konstruktor
    ~KlasseB();    //Destruktor

    KlasseA* p;       // Zeiger vom Typ KlasseA
    void func_b();
    void set_p(KlasseA* kl);
    ...
  private:
    ...  
};

...

int main(){
  KlasseA kla;
  KlasseB klb;

  kla.set_p(&klb);
  klb.set_p(&kla);

  kla.p->func_b();
}
*
Dieses Programm läuft sogar. Von kla (KlasseA) aus wird eine Funktion von klb (KlasseB) aufgerufen,
ABER:
wollte ich nun INNERHALB einer Methode von kla (KlasseA) eine Methode aus der Klasse "KlasseB" aufrufen, gibt der Compiler mir einer Fehlermeldung: "Forward Declaration" - Weil die Methode aus KlasseB innherhalb von KlasseA noch nicht bekannt ist, nur die Klasse selbst, wurde zu Beginn mit "class KlasseB" bekanntgemacht.
Aber _irgendwie_ muss es doch möglich sein, eine solche Beziehung zwischen zwei Klassen herzustellen, oder?  

Weiß jemand, wie man dieses Problem beheben kann? Er würde mir wirklich sehr weiterhelfen

Tausend Dank im Vorraus! - Gruß MaX

P.S.: Wenn jemand ne Lösung findet, darf er sich was drauf einbilden!  - Ich hab inzwischen schon echt viele Leute gefragt - und alle halten es zumindest für machbar - aber keiner weiß, wie's geht...


----------



## Kachelator (18. Februar 2004)

```
// Dies in die Header (.h)
class A
{
public:
  void MethodA1();
};

class B
{
public:
  void MethodB1();
};

// Folgendes könnte in den .cpp-Dateien stehen:

void A::MethodA1()
{
  B b;
  b.MethodB1();
}

void B::MethodB1()
{
  A a;
  a.MethodA1();
}
```
Das geht natürlich auch, wenn die Klassen Pointer auf die jeweilige andere Klasse als Member besitzen anstelle der lokalen As bzw. Bs wie hier.

Solange du die Definition der Klasse und die Deklaration der Klassenmethoden von der Implementerung trennst, hast du da keine Problem mit. 

Hilft dir das weiter? Wenn nicht, frag noch mal nach. Oder schick mal deinen Code - vielleicht kann ich das dann besser erklären.


----------



## basd (18. Februar 2004)

Hallo .

Also wenn du die Klassendeklaration in zwei getrennte Header schreibst diese dann in den CPPs in dennen du die Methoden schreibst includierst (von den beiden Klassen die Header includierst) müsste es funktionieren.


oh da kam mir einer zuvor


----------



## Suehprom (18. Februar 2004)

Na...eigentlich meinte ich das ein bisschen anders. Aber erstmal danke für Deine Antwort.
Also: In Deinem Beispiel wird IN Methode "MethodA1" eine Instanz vom Typ "B" erzeugt. Und darauf zugegriffen.
Meine Frage aber war, ob bzw. WIE es möglich ist, von einem Objekt auf ein anderes zuzugreifen, das bereits existiert.

Hier ein Beispiel: 

```
#include "iostream.h"

class b;

class a{
  private:
    b* v;

  public:
    a(){;}
    void hi1(){cout << "ich bin A!" << endl;};
    void hi2(){v->hi1();};
    b* getval(){return v;}
    void setval(b* val){v=val;}
};

class b{
  private:
  a* v;

  public:
    b(){;}
    void hi1(){cout << "ich bin B!" << endl;};
    void hi2(){v->hi1();};
    a* getval(){return v;}
    void setval(a* val){v=val;}
};

int main(){
  a kla;
  b klb;

  kla.setval(&klb);
  klb.setval(&kla);

  cout << "A: ";
  kla.getval()->hi1();

  cout << endl << endl;

  cout << "B: ";
  klb.getval()->hi1();

  cout << endl;

}
```

Es hängt jeweils an hi2 - wenn das ginge, wäre mein Problem gelöst.

Danke im Vorraus!

Gruß MaX


----------



## Kachelator (18. Februar 2004)

So solltest du auch hi2() problemlos verwenden können:

```
#include "iostream.h"

class b;

class a{
  private:
    b* v;

  public:
    a(){;}
    void hi1(){cout << "ich bin A!" << endl;};
    void hi2();
    b* getval(){return v;}
    void setval(b* val){v=val;}
};

class b{
  private:
  a* v;

  public:
    b(){;}
    void hi1(){cout << "ich bin B!" << endl;};
    void hi2();
    a* getval(){return v;}
    void setval(a* val){v=val;}
};

// das in die cpp 

void a::hi2()
{
  v->hi1();
}

void b::hi2()
{
  v->hi1();
}



int main(){
  a kla;
  b klb;

  kla.setval(&klb);
  klb.setval(&kla);

  cout << "A: ";
  kla.getval()->hi1();

  cout << endl << endl;

  cout << "B: ";
  klb.getval()->hi1();

  cout << endl;

}
```
Ich habe die Implementierung der Methode aus der Klassendefinition rausgenommen.


----------



## Suehprom (18. Februar 2004)

*ES GEEEEEEEEEEEEEEEEEHHHHHTT* 

Du bist ein Genie

Das ganze ist nur ein Beispielprogramm gewesen, weil es etwas zu umfangreich gewesen wäre, das Orginal hier reinzustellen, aber ich glaube, dass Du damit gerade tatsächlich mein Problem gelöst hast

Juhuuu

Danke Dir! - Gruß MaX


----------



## Kachelator (18. Februar 2004)

> Du bist ein Genie


  Da übertreibst du, aber ich freue mich doch, dass es funktioniert.


----------



## Suehprom (18. Februar 2004)

*Komando zurück - Es geht immer noch nicht!*

Bitte nicht erschrecken - aber das Problem ist leider immer noch nicht gelöst. Jetzt wird's ein bisschen komplizierter - aber ich hoffe, ihr seht das als Herausforderung, nicht als Problem 

Also:
Im folgenden (leicht abgeändertes Beispiel von oben) kann auf die Klasse zugegriffen werden, aber nicht auf den Wert, den eine Variable gespeichert hält. Warum


```
// test.h

#include "iostream.h"

class b;

class a{
  private:
    b* v;

  public:
    a(){val = 1;}

    int val;
    void wert();

    void setval(b* val){v = val;}
};

class b{
  private:
    a* v;

  public:
    b();

    int val;
    a meinA;
    void wert();

    void setval(a* val){v = val;}
};

//test.cpp

#include "test.h"

void a::wert()
{
  v->val;
}

void b::wert()
{
  meinA.val;
}

b::b(){
  val = 2;
  meinA.setval(this);
}

int main(){
  b klb;

  cout << "A: ";
  klb.wert();

  cout << endl << endl;

  cout << "B: ";
  klb.meinA.wert();

  cout << endl;

}
```

Wieso kann man die Klasse benutzen, aber nicht auf die Werte zugreifen?
Meiner Logik nach müsste die Ausgabe wie folgt lauten:
A: 1

B: 2

Aber stattdessen kommt folgende Ausgabe:
A: 

B:

*WIESO?*

Bin für alle Lösungvorschläge dankbar

Gruß MaX


----------



## basd (18. Februar 2004)

naja musst die Werte halt auch ausgeben 
  cout << "A: " <<  klb.wert();

  cout << endl << endl;

  cout << "B: "  << klb.meinA.wert();


----------



## Kachelator (18. Februar 2004)

```
void a::wert()
{
  v->val;
}

void b::wert()
{
  meinA.val;
}
```
 Könnte es damit zusammenhängen, dass diese Funktionen nichts tun? Etwas drucken oder einen Wert zurückgeben? Naja, sie werten immerhin  Member aus, machen aber nichts damit, also drucken oder so. *blinzel*


--- 
basd war schneller!  
Und hat ausserdem noch einen anderen Fehler entdeckt, der mir entgangen war!


----------



## Suehprom (18. Februar 2004)

ok, das war mein Fehler, sorry - es hat mich eh gewundert, warum *überhaupt keine* Ausgabe kam. Ich hab den Fehler korrigiert und bekomme jetzt genau das falsche Ergebnis, was ich Euch *eigentlich* zeigen wollte:


```
// test.h

#include "iostream.h"

class b;

class a{
  private:
    b* v;

  public:
    a(){val = 1;}

    int val;
    int wert();

    void setval(b* val){v = val;}
};

class b{
  private:
    a* v;

  public:
    b();

    int val;
    a meinA;
    int wert();

    void setval(a* val){v = val;}
};


// test.cpp

#include "test.h"

int a::wert()
{
  v->val;
}

int b::wert()
{
  meinA.val;
}

b::b(){
  val = 2;
  meinA.setval(this);
}

int main(){
  b klb;

  cout << "A: " << klb.wert();

  cout << endl << endl;

  cout << "B: " << klb.meinA.wert();

  cout << endl;

}
```

Ich hoffe ich hab jetzt nichts mehr übersehen.
Die Ausgabe dieses Codes ist:
A: 2293624

B: 2293632

Es wurde also willkürliche Werte aus dem Speicher gefischt und *nicht* 1 und 2 ausgegeben.

Woran kann das liegen?

Mfg MaX


----------



## Kachelator (18. Februar 2004)

```
int a::wert()
{
  return v->val;
}
```

So müsste das aussehen. Was du da im Moment zurückkriegst ist irgendwas - vielleicht die Adresse der Funktion oder so. Nicht das return vergessen!


---
Aaa, erster!


----------



## Suehprom (18. Februar 2004)

heul...warum bin ich so s c h e i ß e?... 
danke Euch

--
aber keine Sorge - da mein echtes Programm immer noch nicht tut,
sondern wieder nur ein weiteres Beispielprogramm, werd ich sicher
noch mal auf Euch zurückgreifen!  

Gruß MaX


----------



## Kachelator (18. Februar 2004)

> heul...warum bin ich so s c h e i ß e?


  Na, manche haben's einfach nicht drauf.  

Nein, im Ernst, mir sind schon blödere Sachen passiert. Wenn man konzentriert daran arbeitet, ein Problem zu lösen, passiert es nun mal gelegentlich, dass man an einer anderen Stelle etwas übersieht. Mach dir deshalb keine Sorgen.



> da mein echtes Programm immer noch nicht tut,
> sondern wieder nur ein weiteres Beispielprogramm, werd ich sicher
> noch mal auf Euch zurückgreifen!


 Nur zu!


----------



## Suehprom (18. Februar 2004)

worin besteht eigentlich der Unterschied zwischen einer .h (Header-datei) und einer .cpp (Quellcode-datei)?

Was, wenn ich die Definintion der Klassen in verschiedene header packe und die dazugehörigen Methoden in cpp-dateien? Muss ich dann die header in die cpp includen und die cpp der beiden klassen in die hauptdatei?
So hab ich das eben versucht und es haut nicht hin.

Hilfe....

danke Euch!
Gruß MaX


----------



## Kachelator (19. Februar 2004)

> Was, wenn ich die Definintion der Klassen in verschiedene header packe und die dazugehörigen Methoden in cpp-dateien? Muss ich dann die header in die cpp includen und die cpp der beiden klassen in die hauptdatei?


  Ja, das mit den Headern stimmt soweit. Die cpp-Dateien werden aber normalerweise nicht mit #include eingebunden sondern seperat übersetzt und der resultierende Objectcode dazugelinkt. Wie das genau gemacht wird, hängt vom Compiler bzw. der Entwicklungsumgebung ab. Falls du MSVC verwendest, musst du die cpp-Dateien in der Baumansicht zum Projekt hinzufügen.


> So hab ich das eben versucht und es haut nicht hin.


  Es wäre hilfreich, wenn du das Nicht-Hin-Hauen etwas erläutern könntest. Was geht denn nicht?


----------

