ERLEDIGT : Anfaengerfehler: Vererbeung - Objekt uebernimmt Aenderung nicht



  • <ZEINSIERTER KÄÄÄSE>

    //Edit 1: Soweit ich weis ist *.cc und *.hh völlig legitim! 🙂 Ich nutze ganz langweilig *.cpp und *.h

    //Edit 2: DU MUSST BEI get_Cola_Fach() eine Referenz zurückgeben!
    Cola_Fach& get_Cola_Fach();
    statt
    Cola_Fach get_Cola_Fach();
    Weil sonst in tu_rein bloss eine temporäre Kopie von Cola_Fach verändert wird und nicht die Instanz im Kühlschrank!! 🙂



  • Ach und bei tu_rein brauchst du auch eine Referenz als Argument!

    //.h
    Cola_Fach& get_Cola_Fach(); 
    int tu_rein(Fach& fach,int menge); 
    
    //.cc
    Cola_Fach& Kuehlschrank::get_Cola_Fach(){
            return colafach;
        } 
    
    int Kuehlschrank::tu_rein(Fach& fach, int menge){
            if(offen_oder_nicht()){//ist offen?
                return fach.tu_sache_rein(menge);
            }
            else{
                cout << "Die Tuer ist zu! Du kannst nichts reintun" << endl;
                return 0;
            }
        }
    

    P.S: Warum schreibe ich so viel käse wenn ich eingeloggt bin? Mit Namen wie asldkhafkolhlsdköasd anonym ist alles besser 😞 😞



  • Habe nun alles von dir umgesetzt pigeon!
    Exzellent so funktioniert es. Ich werde noch ca 10 min darueber nachdenken muessen warum, aber das wird schon.

    habe es oben reineditiert!

    Nochmals Danke. Das lief genial



  • ancestral-knowledge schrieb:

    Exzellent so funktioniert es. Ich werde noch ca 10 min darueber nachdenken muessen warum, aber das wird schon.

    Eine Referenz ist einem Zeiger sehr ähnlich. Wenn du etwas mit einem Getter zurückgibts:

    int klasse::get_schueler()  const { return anzahl; }
    

    Bekommst du nur eine Kopie der Anzahl zurück. Das verändert niemals die Klasseninstanz! Daher kannst du auch hinter einen solchen getter "const" schreiben! (Was du auch tun solltest)

    Wenn du nun eine Referenz zurück gibst, gibst du die Speicheradresse von "anzahl" in deiner Klasse zurück! KEINE KOPIE! Daher kannst du hinter einen solchen getter auch nicht const schreiben, da er ja die Klasse verändern kann! (ausser mit mutable aber das ist nun egal 😃 )

    Probiere doch das alles mal mit Zeigern! Dann wird es möglicherweise klarer... 🤡



  • Habe ich getan:
    Die Rueckgabetypen aus der Klasse Fach.hpp haben demnach einen konstanten Rueckgabetypen, da sie nur eine kopie erzeugen. Dies habe ich nochmal hinzugefuegt oben.

    Bei dem Kuehlschrank jedoch habe ich ja eine Referenz auf mein Cola_Fach, da ich genau das Cola_Fach der Instanz aendern will. So muss der Rueckgabetyp des Getters Cola_Fach& get_Cola_Fach(); auch eine Refernz sein, da ich ja auf die Adresse des Colafaches meiner Instanz will. Wenn ich diese habe muss ich diese auch an tu_rein(Fach& fach, int menge) uebergeben, damit ich nicht auf einer Kopie meines Faches arbeite, sondern auf dem Fach meiner Instanz.

    Ich denke ich habe es verstanden.

    Danke nochmals fuer die Erlaeuterungen



  • Nein.

    Mach wenn schon

    const Cola_Fach& get_Cola_Fach() const; // oder:
    Cola_Fach const& get_Cola_Fach() const; // ist genau dasselbe
    

    sonst ist dein Setter nutzlos und du könntest gerade so gut einen public -Member anbieten. Durch die Const-Referenz kopierst du das Original ebenfalls nicht, aber verhinderst, dass es vom Aufrufer geändert wird. Das sollte auch so sein bei Get-Methoden (Lesezugriff).



  • Nexus schrieb:

    Nein.

    Mach wenn schon

    const Cola_Fach& get_Cola_Fach() const; // oder:
    Cola_Fach const& get_Cola_Fach() const; // ist genau dasselbe
    

    sonst ist dein Setter nutzlos und du könntest gerade so gut einen public -Member anbieten. Durch die Const-Referenz kopierst du das Original ebenfalls nicht, aber verhinderst, dass es vom Aufrufer geändert wird. Das sollte auch so sein bei Get-Methoden (Lesezugriff).

    Ich glaube das lasse ich lieber... habe einfach keine Ahnung was das nun machen soll. Habe es auch einfach mal kurz ausprobiert und dann bekomme ich irgendwelche Probleme bei tu_sache_rein
    "error C2662: 'Fach::tu_sache_rein' : cannot convert 'this' pointer from 'const Fach' to 'Fach &'"

    Trotzdem Dank.



  • dann musst du das so übergeben:
    klasse.tu_was(*this);
    Wenn du das Objekt das hinter einem Zeiger steht (this ist ein Zeiger) willst, dann mach ein * davor. Und gib nicht so schnell auf!! 🙂

    Und da deine Cola beim getter konstant zurückgegen wird (const Cola&) darst du auch keine Methoden auf sie anwenden die die Cola verändern ... da sie ja const(ant) ist...



  • Pigeon schrieb:

    dann musst du das so übergeben:
    klasse.tu_was(*this);
    Wenn du das Objekt das hinter einem Zeiger steht (this ist ein Zeiger) willst, dann mach ein * davor. Und gib nicht so schnell auf!! 🙂

    Und da deine Cola beim getter konstant zurückgegen wird (const Cola&) darst du auch keine Methoden auf sie anwenden die die Cola verändern ... da sie ja const(ant) ist...

    Ich habe versucht eineige Sachen zu beherzigen aber langsam verstehe ich nichts mehr. Wenn eine Methode const ist, dann heisst das ja, dass man damit keine Membervariablen ändern kann.
    Jetzt habe ich das versucht und mein Programm umgebaut: Ich dachte : "Nunja ich will ja mit get_Cola_Fach() tatsaechlich nichts veraendern und habe die Methode const gemacht wie editiert". Damit habe ich mich aber nun wieder an den Anfang katapultiert, denn nun aendert sich das Objekt wieder nicht....

    Das wird immer verwirrender...



  • ancestral-knowledge schrieb:

    Damit habe ich mich aber nun wieder an den Anfang katapultiert, denn nun aendert sich das Objekt wieder nicht....

    Das wird immer verwirrender...

    Das Gefühl habe ich auch. Wolltest du vorhin mit der indirekt über die Get-Methode das Objekt ändern? Zum Beispiel indem du eine Referenz gespeichert hast und dann über diese zugegriffen hast?



  • was ich halt in der main versuche ist zur zeit (die methoden sind alle im erstn post):

    k.showall();
    
    Cola_Fach &cf = k.get_Cola_Fach();
    cout << cf.get_belegt()<< endl; //liefert richtige anzahl 0
    cout <<	cf.get_frei()<< endl;	//liefert richtige anzahl 6
    cout << k.tu_rein(cf,6) << endl;//liefert richtige anzahl 6 (ich tue 6 rein)
    
    k.showall();
    

    Dies liefertirgendwie

    Colaflaschen: 6 noch Platz, 0 drinne
     Unser Kuehlschrank ist offen
    0
    6
    6
     Colaflaschen: 6 noch Platz, 0 drinne  // hier muesste aber 0 noch platz und 6 drinne stehen
    

    Bin drum und dran das einfach hinzuschmeissen. 12 h daran schon gesessen und nichts leuchtet irgendwie ein.



  • Da du von aussen ohnehin voll und ganz auf das Colafach zugreifen willst mach es doch einfach als public member!

    Ansonsten nimmst du den getter: Cola_Fach& get_Cola_Fach(); Jedoch macht das wie Nexus schon schrieb ned allzu viel Sinn ...

    class Kuehlschrank
    {
    /* bla bla blub */
    public:
        Cola_Fach m_colafach;
    /*blub bla bla*/
    };
    

    oder nicht? 😕 😕



  • Zu dem Problem mit der unerwarteten Ausgabe: Solchen Fehlern kommst du am besten auf die Spur, indem du den Debugger benutzt und schrittweise den Programm durchgehst. Dann überprüfst du jeweils die Variablen und vergleichst sie mit deiner Vorstellung, wie es sein sollte. So findest du Abweichungen relativ schnell heraus.

    Alternativ kannst du das auch mit Debugging-Ausgaben (z.B. std::cout ) hinkriegen. Aber der Debugger ist schon sehr mächtig, sich damit auseinanderzusetzen kann sich schnell lohnen. Zudem brauchst du dabei nicht deinen Code zu ändern...



  • Pigeon schrieb:

    //Edit 1: Soweit ich weis ist *.cc und *.hh völlig legitim! 🙂 Ich nutze ganz langweilig *.cpp und *.h

    .cpp mochte ich noch nie, das erinnert mich immer an cpp den C-Präprozessor. ".C" ist für C++ auch noch üblich, man sollte dazu sagen auf UNIX Systemen. Auf einem DOS hätte das reichlich Probleme verursacht.



  • ~john schrieb:

    .cpp mochte ich noch nie, das erinnert mich immer an cpp den C-Präprozessor.

    Deswegen nimmst du die Endung nicht? 🙂

    Ich finde den Präprozessor sehr interessant. Aber davon abgesehen ist .cpp wohl die am meisten verbreitete Endung für C++-Implementierungsdateien. Ich nehme selber immer .cpp, .hpp und .inl bei Template-Implementierungen.



  • DAnke an alle,

    ich habe es nun einfach public gemacht, wie ihr gesagt habt. macht tatsaechlich gleich viel Sinn. nebenbei habe ich noch den Umgang mit dem Visual 2008 Debugger gelernt.. also breakpoints usw. immerhin ich denke das wird viele Fragen in Zukunft vermeiden.

    Guten Abend


Anmelden zum Antworten