Forum: PC-Programmierung Iterator zugriff auf abgeleitete Klasse


von helpme91 (Gast)


Lesenswert?

Hallo zusammen,

ich bräuchte eure Hilfe.
Ich habe ein C++ Programm in visual studio geschrieben.

Dies sieht folgendermaßen aus:

Ich habe eine Basisklasse + zwei weitere Klassen die von der Basisklasse 
erben.
Funktion alles bereits.

Jetzt gibt es noch eine 4 Klasse, die nichts vererbt bekommt.
Diese soll nur Verwalten.
In dieser Klasse habe ich eine Liste mit Iterator erstellt.
Nun möchte ich mit diesem Iterator auf die Methoden der abgeleiteten 
Klassen zugreifen.
Leider findet der Iterator immer nur Methoden aus der Basisklasse, aber 
nicht aus den beiden abgeleiteten, obwohl die Methoden public sind.

So sieht meine Liste aus:

list <Bestellung*> liste;
list <Bestellung*>::iterator it;

// Hier möchte ich die Methode aufrufen:
(*it)->...Methoden der abgeleiteten Klassen......;

Wie geht das?

: Verschoben durch Moderator
von Oliver S. (oliverso)


Lesenswert?

helpme91 schrieb:
> Wie geht das?

Ohne cast gar nicht.

Oliver

von helpme91 (Gast)


Lesenswert?

Wie kann ich die komplette liste einfach auf der Konsole ausgeben?

von c-hater (Gast)


Lesenswert?

helpme91 schrieb:

> // Hier möchte ich die Methode aufrufen:
> (*it)->...Methoden der abgeleiteten Klassen......;
>
> Wie geht das?

Nur mit cast. Was natürlich ein saublöde Lösung wäre, weil dann für alle 
Fälle möglicher Erben verzweigt werden müsste.

Oder anders ausgedrückt: Dein Konzept ist grundfalsch.

von Klaus W. (mfgkw)


Lesenswert?

Wenn ich dein Problem richtig verstanden habe, fehlt dir virtual vor den 
Methoden, die du aufgerufen haben willst.

Ohne das virtual kommt der Compiler nicht auf die Idee, in den 
Ableitungen nach einer Methode zu suchen.
1
// Time-stamp: "18.09.21 18:30 bestellung.cpp klaus.wachtler@esolutions.de"
2
//
3
// g++ -Wall --std=c++17 bestellung.cpp -o bestellung && ./bestellung
4
5
#include <iostream>
6
#include <string>
7
#include <list>
8
9
10
class Bestellung
11
{
12
public:
13
  Bestellung( const std::string &name )
14
    : name( name )
15
  {
16
  }
17
18
  virtual void zeigDich()
19
  {
20
    std::cout << "ich bin eine Bestellung " << name << std::endl;
21
  }
22
23
protected:
24
  std::string    name;
25
};
26
27
class Expressbestellung: public Bestellung
28
{
29
public:
30
  Expressbestellung( const std::string & name )
31
    : Bestellung( name )
32
  {
33
  }
34
35
  virtual void zeigDich()
36
  {
37
    std::cout << "ich bin eine Expressbestellung " << name << std::endl;
38
  }
39
};
40
41
class Schneckenbestellung: public Bestellung
42
{
43
public:
44
  Schneckenbestellung( const std::string & name )
45
    : Bestellung( name )
46
  {
47
  }
48
49
  virtual void zeigDich()
50
  {
51
    std::cout << "ich bin eine Schneckenbestellung " << name << std::endl;
52
  }
53
};
54
55
56
int main( int nargs, char **args )
57
{
58
  std::list< Bestellung* >   meineliste;
59
  meineliste.push_back( new Bestellung( "per Bote" ) );
60
  meineliste.push_back( new Expressbestellung( "UPS" ) );
61
  meineliste.push_back( new Schneckenbestellung( "DHL kommt vielleicht auch irgendwann an" ) );
62
63
  for( auto it: meineliste )
64
  {
65
    it->zeigDich();
66
  }
67
  return 0;
68
}


Gibt bei mir aus:
1
klaus@lap7:~$ g++ -Wall --std=c++17 bestellung.cpp -o bestellung && ./bestellung
2
ich bin eine Bestellung per Bote
3
ich bin eine Expressbestellung UPS
4
ich bin eine Schneckenbestellung DHL kommt vielleicht auch irgendwann an

Lasse ich die virtual weg, kommt nur noch:
1
klaus@lap7:~$ g++ -Wall --std=c++17 bestellung.cpp -o bestellung && ./bestellung
2
ich bin eine Bestellung per Bote
3
ich bin eine Bestellung UPS
4
ich bin eine Bestellung DHL kommt vielleicht auch irgendwann an

Das heißt, es wird ohne virtual immer die Methode aus der Basisklasse 
genommen.

: Bearbeitet durch User
Beitrag #6824769 wurde von einem Moderator gelöscht.
von Klaus W. (mfgkw)


Lesenswert?

c-hater schrieb im Beitrag #6824769:
> Letztlich ist es also (wie so oft) ein trade off zwischen Speicherbedarf
> und Rechenzeit, welche der beiden Möglichkeiten man verwendet. Deswegen
> habe ich oben das "richtig" auch in Anführungszeichen gesetzt. Um
> anzudeuten, dass es manchmal durchaus auch richtig (im Sinne von
> "sinnvoll") sein kann, das eigentlich falsche und verpönte zu tun...

Nein, ist es (hier zumindest) absolut nicht.
Der "richtige" Weg ist auch ohne Anführungsstriche der richtige, der 
andere ist Murks.

Hast du doch selbst schon gesagt:

c-hater schrieb:
> Nur mit cast. Was natürlich ein saublöde Lösung wäre, weil dann für alle
> Fälle möglicher Erben verzweigt werden müsste.
>
> Oder anders ausgedrückt: Dein Konzept ist grundfalsch.

Außer dem "Nur" hattest du doch recht. Bleib doch dann auch dabei...

von c-hater (Gast)


Lesenswert?

Klaus W. schrieb:

> Nein, ist es (hier zumindest) absolut nicht.
> Der "richtige" Weg ist auch ohne Anführungsstriche der richtige, der
> andere ist Murks.

Das weisst du woher? Also ich jedenfalls bräuchte für diese Entscheidung 
zumindest drei Informationen:

1) Anzahl der Erben-Klassen
2) Anzahl der Objekt-Instanzen
3) Menge des verfügbaren Speichers

Selbst wenn man mal annehmen wollte, dass zumindest Punkt 1 mit dem TO 
erschöpfend behandelt ist, bleiben da doch noch zwei sehr wesentliche 
Punkte...

Also ich würde sowas nicht mit deiner Stringenz entscheiden wollen 
OHNE die Kenntnis dieser Fakten...

Aber was weiss ich schon, ich programmiere ja erst seit 40 Jahren und 
verdiene seit 30 Jahren meinen Lebensunterhalt damit...

Aber ja: vor ca. 30 Jahren hätte ich vielleicht noch genauso 
argumentiert wie du. Da hatte ich ungefähr gerade den OO-Kram wirklich 
verstanden und fand das endlos geil. Aber: man lernt dazu...

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.