Zugriff einer Instanz auf ein Attribut einer anderen Klasse funktioniert nicht



  • Hallo zusammen,

    ich verzweifle an meiner Übung zu C++ und hoffe ihr könnt mir helfen. In der Methode getraenkeWaehlen versuche ich mit der Instanz flaschomat auf eine Methode der Klasse kasten zuzugreifen und die Attribute/Variable getraenk aufzurufen. Dabei bekomme ich immer Fehlermeldungen oder das Programm stürzt gant ab.

    Exakt geht es mir um diese Zeile (84):

    cout << index+1 << " - " << flaschomat->getGetraenk(getraenk[index]) << endl;

    Was mache ich falsch 😞 wie muss ich den Code schreiben, damit flaschomat auf getGetraenk zugreifen kann und das Menu bzw. die Auflistung der Getränke aufrufen kann?

    Hier mein ganzer Code:

    #include <iostream>
    #include <cmath>
    using namespace std;
    
    //die Vereinbarung der Klasse kasten
    
    class kasten
    {
    //die Attribute - privat
    
    string getraenk[3];
    //die Methoden - öffentlich
    public:
    
        // der Konstruktor
        kasten();
        // der Destruktor
        ~kasten();
        // Auswahlmenu
        string getGetraenk();
    
    };
    
    //der Konstruktor
    kasten::kasten()
    {
        //die Getränke eintragen
        getraenk[0] = "Limonaddddddde";
        getraenk[1] = "Wasser";
        getraenk[2] = "Bier";
    }
    
    string kasten::getGetraenk()
    
    {
        getraenk[0] = "Limonade";
        getraenk[1] = "Wasser";
        getraenk[2] = "Bier";
    }
    
    //die Vereinbarung der Klasse getraenkeautomat
    class getraenkeautomat
    {
    
        //jetzt ist der kasten Teil des Getränkeautomaten
    
        kasten *flaschomat;
    
        public:
        //die Methoden
        //der Konstruktor
    
        getraenkeautomat(kasten *tempFlasche);
        //der Destruktor
        ~getraenkeautomat();
        int getraenkeWaehlen();
    
    };
    
    getraenkeautomat::getraenkeautomat(kasten *tempFlasche)
    {
    
        //die Instanz des kasten wird zugewiesen
    
        flaschomat = tempFlasche;
    }
    
    getraenkeautomat::~getraenkeautomat()
    {
        cout << "Eine Instanz der Klasse getraenkeautomat wurde zerstoert." << endl;
    }
    
    int getraenkeautomat::getraenkeWaehlen()
    {
        int auswahl, anzahl;
    
        //die Auswahl
        cout << "Bitte waehlen Sie ein Getraenk: " << endl;
        cout << "Es gibt folgende Auswahl: " << endl;
    
        for (int index = 0; index < 3; index++)
        {
            cout << index+1 << " - " << flaschomat->getGetraenk(getraenk[index]) << endl;
        }
        cout << "Geben Sie die gewuenschte Nummer ein: ";
        cin >> auswahl;
    
        return auswahl;
    }
    
    int main()
    {
        int auswahl;
        //Instanz erzeugen
        //der Zeiger auf die Klasse
        getraenkeautomat *automat;
    
        //den kasten erzeugen
    
        kasten *flasche = new kasten();
    
        //der kasten wird jetzt übertragen
        automat = new getraenkeautomat(flasche);
    
        //ein Getränk auswählen
        do {
            auswahl = automat->getraenkeWaehlen();
        } while (auswahl == -1);
    
        //die Instanzen freigeben
        delete(automat);
    //	delete (flasche);
    
        return 0;
    }
    

    Vielen Dank für die Hilfe.

    LG

    Michelle


  • Mod

    Nun, getraenk gibt es an der Stelle nicht, das ist ein Attribut von kasten. ICh vermute mal, dass kasten::getGetraenk wohl ein getraenk zurück geben soll, aber derzeit setzt das andere Werte für kasten::getraenk und gibt dann anschließend nichts zurück, obwohl die Signatur vorgibt, dass es einen string zurück würde. Das passt nicht zusammen.

    Überhaupt solltest du in deinem ganzen Programm mal überdenken, ob alles üerhaupt das ist, was du dran schreibst, was es wäre. Warum ist ein Getränk drei Strings? Warum besteht dein Kasten aus einem solchen Getränk? getGetraenk habe ich ja schon erwähnt, wobei sich die zusätzliche Frage stellt, warum ein Getränk plötzlich nur noch ein einzelner String ist. Warum hat ein Getränkeautomat einen Verweis auf einen Kasten? Warum nennst du diesen Kasten manchmal auf Flasche? Wenn dir jemand im echten Leben einen Getränkeautomat so beschrieben würde, würdest du ihn für verrückt halten.

    Und noch ein paar technische Hinweise:
    Warum braucht kasten deiner Meinung nach einen selbstdefinierten Destruktor? Du definierst ihn auch nirgends. Das wird später schiefgehen. Ähnliches gilt für getraenkeautomat, wobei du dort wenigstens etwas ausgibst im Destruktor, also scheinst du dein Gründe für den selbstdefinierten Destruktor zu haben. Wundere dich aber hinterher nicht, wenn mehr Automaten zerstört werden als du erwartest, schließlich verletzt du hier die Regel der großen Drei (einfach mal googeln).

    Überhaupt sind die Besitzverhältnisse völlig unklar beim Automaten. Der hat bei dir ja einen Verweis auf einen Kasten (was ich bereits kritisiert habe). Gehört ihm der Kasten? Derzeit übernimmt der Automat keine Verantwortung für den Kasten. Aber auch niemand sonst. Am Ende hast du daher ein dickes Speicherleck.

    A propos Speicherleck: Gute Faustregel für C++: new/delete brauchst du niemals! Ist praktisch immer falsch. Warum sind die beiden Sachen, die du mit new/delete anlegst bei dir keine ganz normalen Variablen? Ihr Lebenszeit ist jedenfalls identisch zu einer ganz normalen Variablen im gleichen Scope. Aber im Gegensatz zu dir (siehe oben) hätte der Compiler keine Speicherlöcher erzeugt.



  • Hallo SeppJ,

    vielen Dank für Deine Antwort. Ich weiß es sehr zu schätzen, wenn sich jemand das alles durchliest und so eine lange Antwort schreibt.

    Zu meinem Hintergrund:

    Im Rahmen eines Fernstudiums lerne ich C++. Dabei lerne ich es so wie man es mir vorgibt. Zeitlich habe ich leider keine andere Möglichkeiten, zusätzlich noch ein Buch lesen, schaffe ich vom Rahmen her leider nicht.

    Daher erhoffe ich mir kurz und schnell Hilfe hier im Forum.

    Warum ich es so gemacht habe wie ich es gemacht habe:

    Das es getraenk an der Stelle nicht gibt, da es ein Attribut von kasten ist, ist mir bewusst. Daher habe ich die Instanz von Kasten in main erstellt und an getraenkeautomat übergeben. So habe ich es gelernt, auch das ich mit den Bezeichnungen der Instanz (flasche,tempFlasche, flaschomat) so arbeiten soll. Die Methode soll den String analog Index der Variable getraenk zurückgeben.

    Mein Auftrag ist es,im Rahmen von objektorientiertet Programmierung (OOP), eine Klasse für die Getränke zu bilden. Dabei muss die Datenkapselung eingehalten werden. Also versuche ich in getraenkeWaehlen auf die Klasse kasten zuzugreifen um das private Attribut getraenk aufzurufen. Dabei mache ich einen Fehler den ich nicht erkennen kann. Meine Syntax ist an der Stelle nicht korrekt. Ich habe auch vieles ausprobiert, komme aber auf keine Lösung.

    Den Destruktor vom kasten definiere ich noch. An der Stelle war ich noch nicht.
    Später soll getraenkeautomat auch noch weitere Methoden anderer Klassen im Rahmen von OOP aufrufen. Das Programm reduziert sich bisher nur auf die eine Methode, die ein Menu der Getränkeauswahl anbieten soll.

    Zu new/delete: ich habe es so gelernt und ich muss es im Autrag auch so umsetzen. Ich bin aber gern bereit, andere Lösungsvarianten zu lernen. Aktuell muss ich mich halt sehr danach richten, was mir vorgegeben wird. Trotzdem danke für den Tipp!

    Ich wäre wirklich sehr dankbar, wenn mir jemand auf die Sprünge hilft, was ich falsch geschrieben habe.

    LG

    Michelle



  • Im Rahmen eines Fernstudiums lerne ich C++. Dabei lerne ich es so wie man es mir vorgibt.

    DAS interessiert hier niemanden

    Zeitlich habe ich leider keine andere Möglichkeiten, zusätzlich noch ein Buch lesen, schaffe ich vom Rahmen her leider nicht.

    und DAS ebenso wenig
    Wenn du glaubst dass dir hier jemand deine Hausaufgaben macht... obwohl, ein paar Übergutmenschen gibt es hier ja.
    Es gibt im Netz massenhaft Beispiele, wie Klassen korrekt instanziiert werden, wenn du selbst dafür zu faul bist, blas dein Fernstudium ab!



  • Furz3000 schrieb:

    Im Rahmen eines Fernstudiums lerne ich C++. Dabei lerne ich es so wie man es mir vorgibt.

    DAS interessiert hier niemanden

    Zeitlich habe ich leider keine andere Möglichkeiten, zusätzlich noch ein Buch lesen, schaffe ich vom Rahmen her leider nicht.

    und DAS ebenso wenig
    Wenn du glaubst dass dir hier jemand deine Hausaufgaben macht... obwohl, ein paar Übergutmenschen gibt es hier ja.
    Es gibt im Netz massenhaft Beispiele, wie Klassen korrekt instanziiert werden, wenn du selbst dafür zu faul bist, blas dein Fernstudium ab!

    Offtopic: Ein Zitat aus einem Linux-Forum:

    ...[C++ Programmierer] Sie sind extrem unfreundlich. Vor allem das oben zitierte c-plusplus.net...

    @Michelle:

    Hier versuchst du getGetraenk mit einem Parameter aufzurufen.

    getGetraenk(getraenk[index]) //
    

    Weder in der Deklaration noch in der Definition hat die Funktion einen Parameter.

    string kasten::getGetraenk()
    

    Außerdem, das hat SeppJ bereits geschrieben, gibt deine Funktion keine Werte zurück (return ...).

    Edit: Und noch außerdem kennst du doch die Getränke noch gar nicht. Es sollte also eher:

    getGetraenk(index) // Getränk mit einem bestimmten Index holen
    

    lauten.



  • temi schrieb:

    Offtopic: Ein Zitat aus einem Linux-Forum:

    ...[C++ Programmierer] Sie sind extrem unfreundlich. Vor allem das oben zitierte c-plusplus.net...

    Steht da auch zufällig was über die Qualität der Fragen, gerade bei Anfängern, oder über die Eigeninitiative die diese meistens mitbringen? 3 Zeilen abgeschrieben Code abtippen, kompilieren...-> geht nicht (weil sogar fürs Abtippen zu wenig Disziplin da ist). Anstatt die Compilererrors zu lesen und selbst herausfinden, wieso "es nicht geht", wird obligatorisch 2-3 Minuten geweint. Anschließend weint man hier im Forum weiter. Und dann fragt man sich, weshalb es manche hier an die Nerven bekommen.

    Zu dem aktuellen Beitrag: Glaubst du ernsthaft, dass du dem TE hier mit einer Lösung auf dem Silbertablett in irgendeiner Art und Weise hilfst?! Das Gegenteil ist der Fall.
    Sowas etabliert sich gemäß dem Motto: "Wenn irgendwas nicht geht, weine solange rum bis es jemand für dich macht." Somit baut man aus reinen "übergutmenschlichen" Gründen eine while(1) und die Menschheit wird exponentiell immer mehr weinen...



  • temi schrieb:

    Offtopic: Ein Zitat aus einem Linux-Forum:

    Linus Torwalds schreibt da nicht 😉


  • Mod

    Bitte beim Thema bleiben. Wenn einem die Einstellung des Threaderstellers missfällt, dann kann man auch einfach nicht antworten. Das ist doch genau im Sinne des Erfinders, dass schlechten Fragestellern nicht, oder weniger gut, geholfen wird.

    Wenn man einem Fragesteller mit einer missfälligen Einstellung helfen möchte, diese zu ändern, dann kann und sollte man dies auf angemessene Art und Weise tun. Niemand hat je seine Einstellung geändert, weil man ihn ob seiner Einstellung beleidigt hat.

    Im Zweifelsfalle sollte es reichen, folgenden Link zu posten. Weniger höflich braucht man nie werden:
    Wie man Fragen richtig stellt



  • Vielen Dank temi und SeppJ für eure Unterstützung.


Anmelden zum Antworten