Vererbungsproblem



  • Hallo,

    habe beim Vererben das Problem, dass ich nicht weiß wie ich die Unterklasse im main aufrufen kann 😞
    Wäre suer wenn mir da jemand helfen kann.

    Fehlermeldung lautet class Affe has no member named Schimpanse

    affe.h

    #ifndef AFFE_H
    #define AFFE_H
    #include <string>
    #include <iostream>
    using namespace std;
    
    class Affe
    {
    public:
        Affe(string name);
        string getname();
        void essen();
        void sitzen();
        string name;
    
    };
    
    #endif // AFFE_H
    

    gorilla.h

    #ifndef GORILLA_H
    #define GORILLA_H
    #include "affe.h"
    #include <string>
    #include <iostream>
    using namespace std;
    
    class Gorilla : public Affe
    {
    public:
        Gorilla();
        void trommelt();
        void essen();
        void sitzen();
    };
    #endif // GORILLA_H
    

    schimpanse.h

    #ifndef SCHIMPANSE_H
    #define SCHIMPANSE_H
    #include "affe.h"
    #include <string>
    #include <iostream>
    using namespace std;
    
    class Schimpanse: public Affe
    {
    public:
        Schimpanse();
        void hangelt();
        void essen();
        void sitzen();
    };
    
    #endif // SCHIMPANSE_H
    

    affe.cpp

    #include "affe.h"
    #include <string>
    #include <iostream>
    using namespace std;
    
    Affe::Affe(string name)
    {
        this->name = name;
    }
    
    string Affe::getname(){
        return name;
    }
    
    void Affe::essen(){
        cout << name << " isst eine Banane" << endl;
    }
    
    void Affe::sitzen(){
        cout << name << " sitzt herum" << endl;
    }
    

    gorilla.cpp

    #include "gorilla.h"
    #include <string>
    #include <iostream>
    using namespace std;
    
    void Gorilla::trommelt(){
        cout << name << " trommelt" << endl;
    }
    
    #include "gorilla.h"
    #include <string>
    #include <iostream>
    using namespace std;
    
    void Gorilla::trommelt(){
        cout << name << " trommelt" << endl;
    }
    

    schimpanse.cpp

    #include "schimpanse.h"
    #include <string>
    #include <iostream>
    using namespace std;
    
    void Schimpanse::hangelt(){
        cout << name << "hangelt" << endl;
    }
    

    main.cpp

    #include <QCoreApplication>
    #include <string>
    #include "affe.h"
    #include "schimpanse.h"
    #include "gorilla.h"
    using namespace std;
    
    int main()
    {
    
        Affe Ursus("Ursus");
        Affe Tschita("Tschita");
        Affe George("George");
    
        Ursus.sitzen();
        Ursus.essen();
        George.Schimpanse.hangelt();
        Tschita.essen();
    
        George.essen();
    
        return 0;
    }
    


  • Wenn du einen Schimpansen willst, musst du auch einen anlegen und nicht einen Affen.



  • Und wie?



  • Schimpanse george("George");
    
    george.hangelt();
    

    PS:

    #include <string>
    #include <iostream>
    

    brauchst du nicht immer wieder in den Headerdateien der abgeleiteten Klassen zu wiederholen, da diese ja schon über "affe.h" eingebunden sind.

    Und bitte entferne

    using namespace std;
    

    aus deinen Headerdateien (ein globales "using namespace" in Headerdateien ist ganz böse).
    In Headerdateien direkt den Namensbereich verwenden:

    std::string
    

    (alternativ für Fortgeschrittenene: "using std::string")



  • Natürlich müssen die abgeleiteten Klassen im Konstruktor noch den Namen entgegennehmen und an den Affen weiterleiten.



  • Schimpanse george("George"); 
    
    george.hangelt();
    

    Wie kann das funktionieren, muss ich in der Schimpanse.cpp es dann gleich programmieren wie in der affe.cpp? Wenn ja was ist den der Sinn vom Vererben? Sollte doch dadurch weniger Aufwand sein...



  • frei aus dem bauch geschrieben

    class Affe
    {
       public:
          Affe(const std::string &n) : name(n) { }
          string getname() { return name; }
          virtual void essen() { std::cout << "ist mit den haenden\n"; }
          void sitzen() { std::cout << "setzt sich\n"; }
    
       private:
          string name;
    };
    
    class Gorilla : public Affe
    {
       public:
          // using Affe::Affe; geht ab 0x11 oder 0x14. weiß net genau
          Gorilla(const std::string &n) : Affe(n) {  }
          void trommelt() { std::cout << "trommelt\n"; }
          virtual void essen() { std::cout << "isst mit besteck\n"; }
          // void sitzen(); brauchen wir hier nicht, weil es nicht Affe::sitzen ueberschreibt
    };
    
    class Schimpanse: public Affe
    {
       public:
          Schimpanse(const std::string &n) : Affe(n) { }
          void hangelt() { std::cout << "hangelt sich durch die prärie\n"; }
          //void essen(); brauchen wir nicht. isst auch mit den haenden
          //void sitzen(); sitzt wie ein affe. also bruachen wir das auch nicht
    };
    
    int main()
    {
    
        Affe Ursus("Ursus");
        Schimpanse Tschita("Tschita");
        Gorilla George("George");
    
        Ursus.sitzen();
        Ursus.essen();
        George.hangelt();
    
        Tschita.essen();
    
        George.essen();
    
        return 0;
    }
    


  • Vielen Dank für deine super Antwort 🙂
    Nun ist mir schon einiges klarer.

    Das Problem ist nur,dass ich ein Teil in der Header und den anderen Teil in der .cpp programmieren muss, so wie ich es oben rein gestellt habe. Kannst du mir evtl. noch an einer Klasse aufzeigen wie das auszusehen hat?



  • so wie du es vorher schon gemacht hast. die definition in eine cpp

    // header datei
    class Affe
    {
       public:
          Affe(const std::string &n);
          const std::string& getname() const;
          virtual void essen() const;
          void sitzen() const;
    
       private:
          std::string name;
    };
    
    // cpp datei
    Affe::Affe(const std::string &n) : name(n) 
    {
    }
    
    const std::string& getname() const
    {
       return name;
    }
    
    void Affe::essen() const
    {
       std::cout << "ist mit den haenden\n";
    }
    
    void Affe::sitzen() const
    {
       std::cout << "setzt sich\n";
    }
    

    mit const-correctness



  • Vielen Dank habe nun das Programm so hin bekommen wie ich es wollte 🙂
    Musste nur noch string name von private in public ändern 😉

    Wie funktioniert das ganze eigentlich mit dem Erweiterungsprinzip anstatt mit dem Ersetzungsprinzip?



  • warum in public aendern ?



  • Da ich in Gorilla.cpp und Schimpanse.cpp auf den Namen zugreifen muss, dass du jedoch ja nicht wissen konntest.

    Wollte nun noch die Affenart sprich Schimpanse und Gorilla hinzufügen. Hänge aber wieder an einem Problem 😕

    Dachte man kann es so machen aber dann kommt der Fehler "multipleinitalizations"

    #ifndef AFFE_H
    #define AFFE_H
    #include <string>
    #include <iostream>
    using namespace std;
    
    class Affe
    {
    public:
        Affe(const string &n, const string &a);
        const string getname() const;
        const string getart() const;
        void essen() const;
        void sitzen() const;
        string name;
        string art;
    };
    
    #endif // AFFE_H
    
    #include <QCoreApplication>
    #include <string>
    #include "affe.h"
    #include "schimpanse.h"
    #include "gorilla.h"
    #include "affenforscherin.h"
    using namespace std;
    
    int main()
    {
        Affe Ursus ("Ursus", "Affe");
        Schimpanse Tschita ("Tschita", "Schimpanse");
        Gorilla George ("George", "Gorilla");
    
        Ursus.sitzen();
        Ursus.essen();
        Tschita.hangelt();
        Tschita.essen();
        George.trommelt();
        George.essen();
    
        return 0;
    }
    


  • Du wolltest das aber nur mitteilen und den Fehler selber beheben, da du ja weder die exakte Fehlermeldung noch den Code, der dazu führt, zeigst?



  • Chris9090 schrieb:

    Da ich in Gorilla.cpp und Schimpanse.cpp auf den Namen zugreifen muss, dass du jedoch ja nicht wissen konntest.

    Das ist keine Erklärung, denn der getter war auch vorher public.

    int main()
    {
        Affe Ursus ("Ursus", "Affe");
        Schimpanse Tschita ("Tschita", "Schimpanse");
        Gorilla George ("George", "Gorilla");
    

    Du hast die Art jetzt irgendwie doppelt drin, einmal als zusätzlichen String und dann noch als Typ. Das erscheint mir wenig sinnvoll.



  • Dachte man kann dies irgendwie so lösen, aber in dem Fall bin ich auf dem völlig flschen weg :/:/

    Ich stell euch vllt am besten mal meine Aufgabenstellung rein vllt. könnt ihr es dann am besten nachvollziehen.

    Aufgabe 2: Okongo III
    Die Affenforscherin "Besine Gadegas" wandert durch den Dschungel am Fluss Okongo, um das Verhalten unterschiedlicher Affenarten zu erforschen. Immer, wenn sie den Schimpansen "Tschita" oder den Gorilla "George" besucht, vollführt dieser sein typisches Verhaltensmuster und isst danach eine Banane. Implementieren Sie die Besuchssituation auf der Grundlage Ihrer Lösung der ersten Dschungelaufgabe vom letzten Übungsblatt in der folgenden Weise:
    Legen Sie ein neues Projekt an. Kopieren Sie in dessen Verzeichnis die Dateien der unterschiedlichen Affen aus der Aufgabe Okongo II des letzten Übungsblatts. Importieren Sie danach diese Dateien in das neue Projekt. Unter QtCreator geschieht das Importieren durch Rechtsklick auf den Projektnamen und Aufruf des Befehls Existierende Datei hinzufügen.
    Führen Sie dann die im Folgenden beschriebenen Ergänzungen am Projekt durch. In diesem Zusammenhang sind auch Änderungen an den kopierten Dateien erforderlich.
    Definieren Sie eine Klasse Affenforscherin, die über eine Methode für das Besuchen von Affen verfügt:

    void besucht(Affe &a)
    

    Affenforscherinnen besitzen einen Namen.
    Rufen Sie alle Methoden, die Handlungen der Affen betreffen, in der Methode besucht() auf und nutzen Sie dabei die dynamische Polymorphie aus.
    Affen können nun zusätzlich mit Hilfe einer Methode string werBinIch() Auskunft über ihre Art geben.

    Schreiben Sie eine main(...)-Funktion, in der die Forscherin besine den Affen ursus, den Schimpansen tschita und den Gorilla george besucht. Alle Ausgaben auf die Konsole finden in den Klassen der Affenforscherin und der Affenarten und nicht in der main(...)-Funktion statt.

    Ausgabe des Programms:
    Besine besucht den Affen Ursus
    Ursus sitzt herum
    Ursus isst eine Banane
    Besine besucht den Schimpansen Tschita
    Tschita hangelt
    Tschita isst eine Banane
    Besine besucht den Gorilla George
    George trommelt
    George isst eine Banane



  • Kann mir niemand helfen?



  • Doch, wir könnten dir schon helfen und tun das auch gern, aber wir lösen nicht deine Hausaufgaben vollständig. Zumal es dafür auch einfacher wäre, wenn wir den gesamten Quelltext hätten.

    Bevor du aber alles postest, versuche doch das Problem selbst zu lösen. Wenn es nicht geht, dann mach ein minimales (!) vollständiges (!) Beispiel, an dem du das Problem beschreibst.

    Ansonsten vermute ich, dass die Aufgaben irgendwann auf das visitor-Pattern hinauslaufen sollen.



  • Ok danke war wirklich zu viel verlangt von mir.
    Aber keine Sorge es sind nicht meine Hausaufgaben 😛

    Also mein Problem ist ja nicht die ganze Aufgabenstellung. Mein Problem besteht darin die Affenart hinzuzufügen. Ich hab über den Konstruktor ja bereits jedem Affen einen Namen hinzugefügt und nun wollte ich dahinter noch die Affenart hinzufügen was so jedoch leider nicht klappt 😞

    In der Aufgabenstellung steht, dass ich dazu eine Methode verwenden soll, ich weiß jedoch leider nicht wie ich das anstellen soll?



  • manni66 schrieb:

    Du wolltest das aber nur mitteilen und den Fehler selber beheben, da du ja weder die exakte Fehlermeldung noch den Code, der dazu führt, zeigst?



  • Aso sorry wenn ich mich missverständlich ausgedrückt habe.

    Ich wollte die Affenart hinzufügen aber dann kommt die Fehlermeldung "multiple initializiations given for base Affe" und "no matching function for callto Affe::Affe(const string &)"

    Und nun die Frage ob das in meinem Code die komplett falsche herangehensweise ist, oder ob ich darin nur einen Fehler begangen habe?

    Vielen Dank für eure Hilfe und sry für meine missverständliche Frage.

    main.cpp

    #include <QCoreApplication>
    #include <string>
    #include "affe.h"
    #include "schimpanse.h"
    #include "gorilla.h"
    #include "affenforscherin.h"
    using namespace std;
    
    int main()
    {
        Affe Ursus ("Ursus", "Affe");
        Schimpanse Tschita ("Tschita", "Schimpanse");
        Gorilla George ("George", "Gorilla");
    
        Ursus.sitzen();
        Ursus.essen();
        Tschita.hangelt();
        Tschita.essen();
        George.trommelt();
        George.essen();
    
        return 0;
    }
    

    affe.h

    #ifndef AFFE_H
    #define AFFE_H
    #include <string>
    #include <iostream>
    using namespace std;
    
    class Affe
    {
    public:
        Affe(const string &n, const string &a);
        const string getname() const;
        const string getart() const;
        void essen() const;
        void sitzen() const;
        string name;
        string art;
    };
    
    #endif // AFFE_H
    

    affe.cpp

    #include "affe.h"
    #include <string>
    #include <iostream>
    using namespace std;
    
    Affe::Affe(const string &n, const string &a) : name(n), art(a)
    {
    }
    
    const string Affe::getname() const{
        return name;
    }
    
    const string Affe::getart() const{
        return art;
    }
    
    void Affe::essen()const{
        cout << name << " isst eine Banane" << endl;
    }
    
    void Affe::sitzen()const{
        cout << name << " sitzt herum" << endl;
    }
    

    gorilla.h

    #ifndef GORILLA_H
    #define GORILLA_H
    #include "affe.h"
    
    class Gorilla : public Affe
    {
    public:
        Gorilla(const string &n, const string &a);
        void trommelt() const;
    };
    
    #endif // GORILLA_H
    

    gorilla.cpp

    #include "gorilla.h"
    #include <string>
    #include <iostream>
    using namespace std;
    
    Gorilla::Gorilla(const string &n, const string &a) : Affe(n), Affe(a)
    {
    }
    
    void Gorilla::trommelt() const{
        cout << name << " trommelt" << endl;
    }
    

    schimpanse.h

    #ifndef SCHIMPANSE_H
    #define SCHIMPANSE_H
    #include "affe.h"
    
    class Schimpanse : public Affe
    {
    public:
        Schimpanse(const string &n, const string &a);
        void hangelt() const;
    };
    
    #endif // SCHIMPANSE_H
    

    schimpanse.cpp

    #include "schimpanse.h"
    #include <string>
    #include <iostream>
    using namespace std;
    
    Schimpanse::Schimpanse(const string &n, const string &a) : Affe(n), Affe(a)
    {
    }
    
    void Schimpanse::hangelt() const{
        cout << name << " hangelt" << endl;
    }
    

Log in to reply