Forum: PC-Programmierung C++ rekursiv auf eine Klasse zeigen


von Wüli (Gast)


Lesenswert?

Hallo ihr,

ich habe mein Problemchen mal vereinfacht. Ich möchte in der Klasse1, 
viele Objekte von Typ Klasse2 haben, die ihrerseits jeweils auf ein 
Objekt der Klasse1 zeigen. Klasse2 ist quasi ein Knoten könnte man sagen 
(der noch weitere Eigenschaften und Methoden haben soll).

Zur Vereinfachung des Problems, hier nur eine Klasse1 in Klasse2 die 
einen Zeiger auf Klasse1 behinhaltet:
1
#include "Klasse2.h"
2
class Klasse1
3
{
4
  Klasse2 k2;
5
public:
6
  Klasse1();
7
  ~Klasse1();
8
};
1
class Klasse2
2
{
3
  Klasse1* k1;
4
public:
5
  Klasse2();
6
  ~Klasse2();
7
};

Nur leider schmeckt das dem Kompiler nicht. Er kommt mir mit 
Fehlermeldungen wie
* Es fehlt ";" vor "*"
* Unerwartetes Token vor ";"
* Fehlender Typspezifizierer - int wird angenommen

Ist das Problem, dass #include "Klasse2.h" VOR der Deklaration der 
Klasse1 steht und er die Klasse1 noch nicht kennt wenn er die Klasse2 
und somit den Zeiger auf die Klasse1 deklarieren soll? Aber die Klasse1 
in der Klasse2 ebenfalls zu includieren wäre ja noch unsinniger, dann 
beißt sich die Katze ja in den Schwanz.

Weshalb geht das so nicht? Er soll ja lediglich eine Speicheradresse 
speichern in k1...

Bevor ich jetzt irgendein schreckliches Konstrukt aufziehe, könnt ihr 
mir bitte sagen, wie man sowas richtig macht?

Danke!

von Thorsten (Gast)


Lesenswert?

In Klasse2.h:

class Klasse1;

class Klasse2
{
  Klasse1* k1;
public:
  Klasse2();
  ~Klasse2();
};

von Sebastian V. (sebi_s)


Lesenswert?

Wüli schrieb:
> Ist das Problem, dass #include "Klasse2.h" VOR der Deklaration der
> Klasse1 steht und er die Klasse1 noch nicht kennt wenn er die Klasse2
> und somit den Zeiger auf die Klasse1 deklarieren soll?

Genau das. Man kann das ganze durch eine Forward Declaration umgehen. 
Mit der Forward Declaration kannst du dann Pointer auf deine Klasse 
anlegen. Sobald du dann aber auf irgendwelche Member der Klasse 
zugreifen willst brauchst du die volle Deklaration. In der Klasse2.cpp 
wirst du dann vermutlich doch Klasse1.h inkludieren, was an dieser 
Stelle aber nicht mehr zu Problemen führt.

von Wüli (Gast)


Lesenswert?

Prima, danke euch beiden! Jetzt klappts :)

von OOP 4 all (Gast)


Lesenswert?

Sebastian V. schrieb:
> Genau das. Man kann das ganze durch eine Forward Declaration umgehen.

Mmmhhh, das ist aber nicht die OOP Lösung.
Was passiert, wenn du 'Klasse1' überarbeitest, als Ableitung? Dann musst 
du 'Klasse2' auch ändern.

Bei OOP gibt es die späte Bindung: Polymorphie!

https://de.wikibooks.org/wiki/C%2B%2B-Programmierung:_Polymorphie
http://openbook.rheinwerk-verlag.de/oop/oop_kapitel_05_002.htm

von Der Andere (Gast)


Lesenswert?

"OOP 4 all" hat recht. Da das Thema Polymorphie erst mal etwas abstrakt 
ist sollte der TO vieleicht mal konkreter sagen was er will.
Warum hat er diese zyklische Abhängigkeit von jeder Klasse zur jeweils 
anderen?
Ziemlich wahrscheinlich gibt es eine deutlich elegantere Methode dieses 
Problem zu lösen.

von Wüli (Gast)


Lesenswert?

Ich möchte ein >einfaches< neuronales Netz programmieren. Gleich mal 
vorweg, noch versteh ich nicht allzuviel von dem Thema, hab nur die 
ersten paar Seiten eines Buches darüber gelesen. Trotzdem wollte ich 
direkt parallel dazu schon ein wenig experimentieren und dabei meine 
C++-/Softwareengeneeringkentnisse auffrischen (ist ne Weile her). 
Entsprechend gespannt bin ich darauf, wie ihr meint, wie man das 
ordentlich OOP-konform lösen sollte.

Die Klasse1 ist ein Unit bzw. Neuron. Die Klasse2 ist die Verbindung zu 
einem anderen Unit. Ich nenne die Klasse2 LineOut. Lineout enthält einen 
Zeiger auf Unit-Objekt sowie die Gewichtung der Verbindung. Die 
hauptsächlichen Methoden der LineOut-Klasse sind fire()(stimuliert das 
Unit, auf das der Zeiger zeigt) und setWeight(int)(verändert die 
Gewichtung der Verbindung). Ein Objekt der Klasse1, also ein 
Unit-Objekt, kennt mehrere Lineout-Objekte, weil ein Unit mit mehreren 
anderen Units verbunden ist.

Die wichtigste Eigenschaft der Unit-Klasse ist der Schwellenwert. Wenn 
die Summe der Gewichtungen aller LineOut-Objekte die ein Unit 
stimulieren größer ist als dieser Schwellenwert, stimuliert dieses Unit 
seinerseits alle seine LineOut-Objekte, die dann die Units stimulieren, 
auf die sie zeigen.

Sollte das Ergebnis, dass das Netz liefert, richtig sein, sollen die die 
Gewichtungen erhöht werden, die erfolgreich Units stimuliert haben. Ist 
das Ergebnis falsch, werden sie verringert.

Vielleicht hat dieses Konzept den Namen neuronales Netz noch nicht 
verdient, trotzdem geht es in die Richtung und ihr wisst, worauf ich 
hinaus will.


Sollte ein Unit-Objekt seine LineOut-Objekte vielleicht nicht selber 
erzeugen? Oder sollte die Verbindung zwischen Units nicht mit einer 
separaten Klasse gelöst sein?

Bin gespannt!

von Wüli (Gast)


Lesenswert?

...ergänzend dazu...
1
class Neuron
2
{
3
private:
4
  vector<LineOut*> out;
5
  int schwelle;
6
  int accu;
7
  void fireOut();
8
  
9
public:
10
  void addLineOut(Neuron*, int);
11
  void setSchwelle(int);
12
  void fireIn(int);
13
  Neuron();
14
  ~Neuron();
15
};
1
class LineOut : public Line
2
{
3
private:
4
  int weight;
5
  Neuron *unit;
6
7
public:
8
  void fire(int);
9
  void good();
10
  void bad();
11
  void setWeight(int);
12
  int getWeight();
13
  LineOut();
14
  ~LineOut();
15
};

von Wüli (Gast)


Lesenswert?

...sorry, bei LineOut kommt das ": public Line" weg, es gibt da keine 
Basisklasse mehr. Es fehlt außerdem noch die Methode void 
setNeuron(Neuron*) in der Klasse LineOut.

von Duck Mc Scrooge (Gast)


Lesenswert?

Ich weiß nicht, was du unter
>C++-/Softwareengeneeringkentnisse
verstehst. Das kann von Person zu Person variieren. Sind dir "Design 
Pattern" bekannt?

> Das Buch zu dem Thema
ist das eines speziell über Neuronale Netzwerke, oder eines im Sinne von 
"Neuronale Netzwerke unter C++"?

Von der Herangehensweise würde ich mir an deiner Stelle überlegen, was 
deine Neuronen und Verbindungen zu einander ausmacht - hast du ja schon.
Dann Design Patterns durchwühlen und schauen, welches deiner 
Aufgabenstellung am nächsten kommt.
Oder du googlest, ob es verbreitete Pattern für neuronale Netzwerke 
gibt.
Könnte in die Richtung Composite Pattern gehen.

https://www.tutorialspoint.com/design_pattern/composite_pattern.htm

von Der Andere (Gast)


Lesenswert?

Duck Mc Scrooge schrieb:
> Könnte in die Richtung Composite Pattern gehen.
>
> https://www.tutorialspoint.com/design_pattern/composite_pattern.htm

Das gleift hier zu kurz, weil da (siehe Beispiel in dem Link von dir) 
ein "Empoyee" einfach eine Liste von Empoyees hat.
Er muss aber da eine Klasse für die Verbindung definieren, die intern 
noch mindestens eine Eigenschaft hat.
Insofern sehe ich ad hoc keine einfachere Lösung als die vom TO 
angedachte:

Neuron hat eine Liste von Verbindungen
Jede Verbindung hat wieder ein Neuron als Ziel und mindestens eine 
Gewichtung als Attribut.

Also wohl forward Deklaration, aber vieleicht hat noch jemand anderes 
eine bessere Idee

von Duck Mc Scrooge (Gast)


Lesenswert?

Ich sag ja, es könnte in die "Richtung" gehen.
Wenn man die Employe Klasse nach einem Interface (DISCLAIMER) 
implementiert, wird das ganze schon deutlich flexibler. Dann kann man 
verschiedene Klassentypen, welche das Interface implementieren 
ineinander schachteln.

Das riecht ein bisschen nach Baum oder Graph.

von Markus L. (rollerblade)


Lesenswert?

Was soll denn daran rekursiv sein?

von Duck Mc Scrooge (Gast)


Lesenswert?

Ich habe Zweifel, dass der Ausdruck "rekursiv auf eine Klasse zeigen" 
überhaupt Sinn ergibt.

von Mark B. (markbrandis)


Lesenswert?

Markus L. schrieb:
> Was soll denn daran rekursiv sein?

Duck Mc Scrooge schrieb:
> Ich habe Zweifel, dass der Ausdruck "rekursiv auf eine Klasse zeigen"
> überhaupt Sinn ergibt.

Gemeint ist wohl:
Die Objekte von Klasse1 und Klasse2 sollen wechselseitig aufeinander 
zeigen.

von Der Andere (Gast)


Lesenswert?

Wieso?
https://de.wiktionary.org/wiki/Rekursion
Da steht:
"Bedeutungen:
[1] Mathematik: eine Definition, die zur Beschreibung des 
Definitionsgegenstand auf sich selbst verweist"

von Duck Mc Scrooge (Gast)


Lesenswert?

Das ist wohl der springende Punkt, mit dem Composite Pattern baut man 
eine Klasse, wo eine Instanz die auf eine ANDERE Instanz des SELBEN Typs 
zeigt, nicht aber auf sich selbst. Was sollte das auch bewirken?

von OOP 4 all (Gast)


Lesenswert?

Duck Mc Scrooge schrieb:
> Was sollte das auch bewirken?

Ein "This" Pointer wäre doch eine gute Idee, oder? ;->>>

von Duck Mc Scrooge (Gast)


Lesenswert?

this->this

Darf das das?
Das darf das.
...das das das darf...

von Martin H. (horo)


Lesenswert?

Der Andere schrieb:
> Wieso?
> https://de.wiktionary.org/wiki/Rekursion
> Da steht:
> "Bedeutungen:
> [1] Mathematik: eine Definition, die zur Beschreibung des
> Definitionsgegenstand auf sich selbst verweist"

Rekursion: siehe Rekursion

von OOP 4all (Gast)


Lesenswert?

Duck Mc Scrooge schrieb:
> this->this
>
> Darf das das?
> Das darf das.
> ...das das das darf...

this->myownmethod();   // laeuft

von Duck Mc Scrooge (Gast)


Lesenswert?

megaVoid WhatEver::MyOwnMethod()
{
   this->MyOwnMethod()
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.