mikrocontroller.net

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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Wüli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include "Klasse2.h"
class Klasse1
{
  Klasse2 k2;
public:
  Klasse1();
  ~Klasse1();
};
class Klasse2
{
  Klasse1* k1;
public:
  Klasse2();
  ~Klasse2();
};

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!

Autor: Thorsten (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
In Klasse2.h:

class Klasse1;

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

Autor: Sebastian V. (sebi_s)
Datum:

Bewertung
1 lesenswert
nicht 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.

Autor: Wüli (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Prima, danke euch beiden! Jetzt klappts :)

Autor: OOP 4 all (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Der Andere (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Wüli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Wüli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...ergänzend dazu...
class Neuron
{
private:
  vector<LineOut*> out;
  int schwelle;
  int accu;
  void fireOut();
  
public:
  void addLineOut(Neuron*, int);
  void setSchwelle(int);
  void fireIn(int);
  Neuron();
  ~Neuron();
};
class LineOut : public Line
{
private:
  int weight;
  Neuron *unit;

public:
  void fire(int);
  void good();
  void bad();
  void setWeight(int);
  int getWeight();
  LineOut();
  ~LineOut();
};

Autor: Wüli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Duck Mc Scrooge (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Der Andere (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Duck Mc Scrooge (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Markus L. (rollerblade)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Was soll denn daran rekursiv sein?

Autor: Duck Mc Scrooge (Gast)
Datum:

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

Autor: Mark B. (markbrandis)
Datum:

Bewertung
1 lesenswert
nicht 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.

Autor: Der Andere (Gast)
Datum:

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

Autor: Duck Mc Scrooge (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: OOP 4 all (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Duck Mc Scrooge schrieb:
> Was sollte das auch bewirken?

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

Autor: Duck Mc Scrooge (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
this->this

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

Autor: Martin H. (horo)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: OOP 4all (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Duck Mc Scrooge schrieb:
> this->this
>
> Darf das das?
> Das darf das.
> ...das das das darf...

this->myownmethod();   // laeuft

Autor: Duck Mc Scrooge (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
megaVoid WhatEver::MyOwnMethod()
{
   this->MyOwnMethod()
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.