Mit Iterator auf Methoden von abgeleiteter Klasse zugreifen



  • 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 kann ich das machen?


  • Mod

    Sollte eigentlich gehen. virtual vergessen? Ansonsten: Zeig mehr Code.



  •       Hier das program ohne main und ohne der zweiten Klasse.
          Hat aber das gleiche Problem.
    
          #include <string>
          #include <iostream>
          #include <list>
          using namespace std;
          
          
          class Essen {
          protected:
          
          	string produktbezeichnung;
          	int produktID;
          
          public:
          
          	Essen(string iniProduktbezeichnung, int iniProduktID) {
          
          		produktbezeichnung = iniProduktbezeichnung;
          		produktID = iniProduktID;
          	}
          
          	int getID() {
          		return produktID;
          	}
          };
          
          class Lebensmittel : public Essen {
          private:
          
          	struct Datum {
          		int Tag;
          		int Monat;
          		int Jahr;
          	};
          
          	Datum datum;
          
          public:
          
          	Lebensmittel(string iniProduktbezeichnung, int iniProduktID, float inipreis, int iniLagerBestand, Datum iniDatum)
          		:Essen(iniProduktbezeichnung, iniProduktID)
          	{
          		datum = iniDatum;
          	}
          
          	void displayLebensmittel() {
          
          		cout << "Produktbezeichnung: " << produktbezeichnung << endl;
          		cout << "Produkt-ID " << produktID << endl;
          		cout << "Datum " << datum.Tag << "." << datum.Monat << "." << datum.Jahr << endl;
          	}
          
          	Datum getAblaufdatum() {
          		return datum;
          	}
          };
          
          class Verwaltung {
          private:
          
          	list <Essen*> liste;
          	list <Essen*>::iterator it;
          
          public:
          
          	Verwaltung() {};
          
          	void bestellungEinfügen(Essen* produkt) {
          		liste.push_back(produkt);
          	}
          
          	void alleProdukteAnzeigen() {
          
          		cout << "" << endl;
          		cout << "Alle Bestellungen anzeigen des is!!!!" << endl;
          		cout << "" << endl;
          
          		for (it = liste.begin(); it != liste.end(); it++) {
          
          			(*it)->displayLebensmittel; // Hier liegt das Problem
          		}
          	}
          };
          
          void main() {
          
          	// Teststruktur wurde jetzt nich angegeben.
          
          }


  • Deine Liste besteht ja aus Essen*-Elementen, aber displayLebensmittel (btw.: es fehlt noch die Klammern für den Aufruf) gibt es dort nicht, sondern nur in der abgeleiteten Klasse 'Lebensmittel'.
    Also entweder auch die Funktion als virtual oder abstract (= 0) in der Basisklasse definieren oder aber nur Lebensmittel* in der Liste zulassen.

    PS: Üblicherweise nimmt man vector<T> anstatt list<T> (wenn man nicht hauptsächlich Elemente mittendrin hinzufügt).
    Und der Iterator it sollte nur eine lokale Variable (kein Klassenmember sein) - es ist ja kein Zustandswert der Klasse Verwaltung.



  • Funktioniert auch nicht mit den Klammern.
    Kannst du mir im Code kurz zeigen, wie du das machen würdest?
    Kann es nicht ganz nachvollziehen, wenn ich es nicht gesehen habe.

    Danke.



  • Füge

    void displayLebensmittel() = 0;
    

    in die Klasse Essen ein (bzw. die Funktion sollte dann nur jeweils display o.ä. heißen).

    Noch besser, diese wäre virtual und Essen würde selbst seine Daten (produktbezeichnung, produktID) ausgeben und die abgeleiteten Klassenfunktionen rufen dann diese Basisfunktion auf.



  • Funktioniert auch nicht.





  • Das muss ja irgendwie gehen.


  • Mod

    @C91 sagte in Mit Iterator auf Methoden von abgeleiteter Klasse zugreifen:

    Das muss ja irgendwie gehen.

    Geht ja auch, wenn man's richtig macht. Aber mit der Beschreibung "Funktioniert auch nicht." können wir dir halt nicht sagen, was du nicht richtig machst.



  • Ja, ich habe es hinbekommen, danke.

    Aber jetzt habe ich noch ein problem.

    virtual funktioniert bei mir nur, wenn die Methode keinen Rückgabewert hat.

     virtual void displayGetränke() {};
    

    So funktioniert es nicht mehr:

     virtual int getTag() {};
    

    Hier kommt immer die Fehlermeldung: C4716 Muss einen Wert zurückgeben.

    So sieht die getter aus:

     int getTag() {
     	return ablaufdatum.Tag;
     }
    

    Was mache ich jetzt falsch?



  • @C91 sagte in Mit Iterator auf Methoden von abgeleiteter Klasse zugreifen:

     virtual int getTag() {};
    

    Ist das in der Basisklasse? Wenn diese Methode getTag() dort keine sinnvolle Implementierung hat dann mach' sie pure virtual:

    virtual int getTag() const = 0;
    


  • Die getter ist in einer abgeleiteten Klasse.



  • Lebensmittel ist von Essen abgeleitet? WTF?



  • @hustbaer
    hat sich wahrscheinlich nen Wolf gelesen (vorsicht, insider).



  • @C91 sagte in Mit Iterator auf Methoden von abgeleiteter Klasse zugreifen:

    Aber jetzt habe ich noch ein problem.

    So funktioniert es nicht mehr:

     virtual int getTag() {};
    

    Hier kommt immer die Fehlermeldung: C4716 Muss einen Wert zurückgeben.

    Was mache ich jetzt falsch?

    Das geht auch ohne virtual nicht. Wenn die Methode einen Rückgabewert hat, dann muss sie auch etwas zurückgeben. Wie die Fehlermeldung schon sagt.



  • @C91: abgesehen von den Codefragen: was willst du eigentlich modellieren?

    Ansonsten hilft dir vielleicht dieses Beispiel hier:

    #include <iostream>
    #include <memory>
    
    class Basisklasse {
       public:
       int funktion_a();
       virtual int funktion_b();
       virtual int funktion_c() = 0;
       virtual ~Basisklasse() = default; // nicht vergessen!
    };
    
    int Basisklasse::funktion_a() { return 42; }
    int Basisklasse::funktion_b() { return 23; }
    // funktion_c brauchen wir nicht, weil mit =0 als 'pure virtual' markiert
    
    class Kindklasse : public Basisklasse {
        public:
       int funktion_a();
       int funktion_b() override;
       int funktion_c() override;
       int funktion_d();
    };
    
    int Kindklasse::funktion_a() { return 1; }
    int Kindklasse::funktion_b() { return 2; }
    int Kindklasse::funktion_c() { return 3; }
    int Kindklasse::funktion_d() { return 4; }
    
    int main() {
        std::unique_ptr<Basisklasse> pb = std::make_unique<Kindklasse>();  // (man sollte kein new benutzen)
        std::cout << pb->funktion_a() << '\n'; //42 weil nicht virtual
        std::cout << pb->funktion_b() << '\n'; //2
        std::cout << pb->funktion_c() << '\n'; //3
        // pb->funktion_d() geht nicht, weil es funktion_d nicht in Basisklasse gibt
    }
    
    

    Edit: berichtigt.



  • @wob
    funktion_a gibt 1 aus, und funktion_d geht auch ...
    Es wurde die Klasse Kindklasse instanziert.



  • Tja, das passiert, wenn man zuviel auto benutzt.
    Zu Fuß gehen ist viel umweltfreundlicher 🙂



  • @Belli sagte in Mit Iterator auf Methoden von abgeleiteter Klasse zugreifen:

    @wob
    funktion_a gibt 1 aus, und funktion_d geht auch ...
    Es wurde die Klasse Kindklasse instanziert.

    Argh, kommt davon, wenn man zu viel vereinfachen will und das nicht testet. Habs berichtigt.


Log in to reply