Problem mit virtuellen Methoden



  • .filmor schrieb:

    Das liegt daran, dass Essen (int) nicht die gleiche Signatur hat wie Essen (int, int). Nur bei gleicher Signatur wird die Methode überschrieben. Was sollen diese Parameter überhaupt da?

    P.S.: Es gibt weder <iostream.h> noch void main (). Bitte benutze <iostream>, std::cout und int main () stattdessen.

    Ich habe das gerade ausprobiert, beiden die gleiche Signatur zu geben. Dann wird aber nur noch der letzte Wert der Fluegellänge geändert und die beiden anderen nicht mehr.

    Diese Libelle ist 20 cm lang
    und 1g schwer
    Sie hat eine Fluegellaenge von 20 cm
    ------------------------------------

    Diese Libelle ist 20 cm lang
    und 1g schwer
    Sie hat eine Fluegellaenge von 25 cm



  • Du musst dann auch dafür sorgen, dass die geerbte Methode aufgerufen wird:

    void Libelle::Essen ()
    {
        ++fluegellaenge;
        Insekt::Essen ();
    }
    


  • He... das war alles???? Das klappt!!! Du bist ja super!!! Vielen, vielen Dank!! Und ich dachte schon das wäre ein riesen Akt, was da nich stimmt... Ich war echt schon am verzweifeln!

    DANKE!!!!!!! 🙂



  • Etwas "richtiger" wäre das ganze aber so:

    #include <iostream>
    
    class Insekt
    {
    public:
        Insekt (int laenge, int gewicht) : _laenge (laenge), _gewicht (gewicht)
        {}
        virtual void Essen ()
        {
            ++_laenge;
            ++_gewicht;
        }
        virtual void Ausgabe()
        {
            std::cout << "Dieses Insekt ist " << _laenge << " cm lang\n"
                         "und " << _gewicht << "g schwer" << std::endl;
        }
    protected:
        unsigned int getLaenge ()
        { return _laenge; }
        unsigned int getGewicht ()
        { return _gewicht; }
    
    private:
        unsigned int _laenge;
        unsigned int _gewicht;
    };
    
    class Libelle : public Insekt
    {
    public:
        Libelle(int laenge, int gewicht, int fluegellaenge)
            : Insekt(laenge, gewicht), _fluegellaenge (fluegellaenge)
        {}
    
        virtual void Essen ()
        {
            ++_fluegellaenge;
            Insekt::Essen ();
        }
    
        virtual void Ausgabe ()
        {
            std::cout << "Diese Libelle ist " << getLaenge() << " cm lang\n"
                         "und " << getGewicht() << " g schwer\n"
                         "Sie hat eine Fluegellaenge von "
                      << _fluegellaenge << " cm" << std::endl;
        }
    
    private:
        unsigned int _fluegellaenge;
    };
    
    int main()
    {
        Insekt insekt(20,1);
        Libelle libelle(20,1,20);
    
        Insekt* Insekten[2];
        Insekten[0]=&insekt;
        Insekten[1]=&libelle;
    
        Insekten[0]->Ausgabe();
        std::cout << "\n";
        Insekten[1]->Ausgabe();
        std::cout << "--------------------------------------------------\n";
    
        for (int i=0; i<5; i++)
        {
            Insekten[0]->Essen();
            Insekten[1]->Essen();
        }
    
        Insekten[0]->Ausgabe();
        std::cout << "\n";
        Insekten[1]->Ausgabe();
        cout << "--------------------------------------------------\n\n";
    
        cin.get ();
    }
    


  • aber die methoden der unterklasse müssen doch nur dann virtual sein, wenn man von der unterklasse nochmal vererben will und dort die methode wieder "überschreiben" will, oder?



  • Nein. Wenn in einer abgeleiteten Klasse in der Deklaration einer bereits geerbten virtuellen Methode virtual steht, bewirkt das gar nichts. Geerbte virtuelle Methoden bleiben virtuell. Auch weiter abgeleitete Klassen können sie neu definieren. Es ist halt nur übersichtlicher, wenn man weiß, welche Methoden virtuell sind und welche nicht.



  • .filmor schrieb:

    Etwas "richtiger" wäre das ganze aber so:

    Danke, das ist nett. Das drucke ich mir auf jedenfall mal aus, zum späteren Nachsehen... Übernehmen kann ich es 1:1 nicht, da ich den vorgegebenen Code nur bedingt abändern durfte... Trotzdem danke nochmal.



  • @filmor:
    Ich dachte Bezeichner mit Underscore vorneweg seien der Implementierung vorbehalten?



  • AFAIK gilt das innerhalb der Klasse nur für __ (doppelten Unterstrich). Im globalen Namensraum hast du Recht.


  • Mod

    doppelter unterstrich (irgendwo im namen) und beginnender unterstrich mit foplgendem großbuchstaben sind für jeden zweck reserviert (insbesondere eben z.b. macros). andere bezeichner mit unterstrich am anfang sind nur für bezeichner im globalen namensraum reserviert.


Anmelden zum Antworten