Frage zu Quelltext



  • Hallo,

    ich habe eine Frage:

    #include <iostream>
    
    using namespace std;
    
    class Schaf {
    
          private:
          static int zaehler;
          public:
          Schaf() {zaehler++;}; //SCHREIBT MAN NACH DEM KONSTRUKTOR ";"??
          ~Schaf() {zaehler--;};
          void zeige() {cout <<"schafe:" <<zaehler <<endl;}
          };
          int Schaf::zaehler=0;
    
    int main(int argc, char *argv[])
    {
    
        Schaf s1, s2;
    
        s2.zeige();
    
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    

    Dazu habe ich folgende Fragen:

    1. Schreibt man nach dem Konstruktor bzw. Desturktor ; (siehe Quelltext)
    2. Wie rufe ich den Destruktor auf? Ich möchte z.B. Die Instanz s1 zerstören?
    Bei Dynamischen Objekten funktioniert das ja mit delete aber hier??

    Danke!!

    Viele Grüße



  • Hallo,

    1. Nein
    2. Der Destruktor wird automatisch aufgerufen.



  • Danke!

    Mit dem automatisch aufrufen hab ich auch schon mal gehört.

    Wie läuft das denn ab?

    Ich möchte z.B. die Instanz s1 zerstören.
    Danach sollte ja zaehler mit 1 abgespeichert sein?

    Anschließend möchte ich die Methode zeige() aufrufen. Dann müsste ja die Zahl 1 ausgegeben werden, da nur noch ein Schaf existiert?

    Wisst ihr wie das gehen soll?

    Danke!!



  • So:

    #include <iostream>
    
    using namespace std;
    
    class Schaf {
    
          private:
          static int zaehler;
          public:
          Schaf() {zaehler++;}; //SCHREIBT MAN NACH DEM KONSTRUKTOR ";"??
          ~Schaf() {zaehler--;};
          void zeige() {cout <<"schafe:" <<zaehler <<endl;}
          };
          int Schaf::zaehler=0;
    
    int main(int argc, char *argv[])
    {
    
        Schaf s2;
    
        {
          Schaf s1;
          s1.zeige();
        }
    
        s2.zeige();
    
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    


  • JamBoo schrieb:

    Danke!

    Mit dem automatisch aufrufen hab ich auch schon mal gehört.

    Wie läuft das denn ab?

    Der Destruktor wird aufgerufen, wenn die Variable den Gültigkeitsbereich verlässt. In dem Fall also am Ende der main().

    Wenn du ihn früher aufgerufen haben willst (selbst aufrufen ist nicht!) musst du eben einen extra Gültigkeitsbereich schaffen:

    int main()
    {
        Schaf s2;
    
        { 
           Schaf s1;  //Bgeinn Gültigkeitsbereich s1
    
           s2.zeige(); //2
        }             //ende Gültigkeitsbereich von s1, aufruf des Dtors
    
        s2.zeige(); //1
    
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    

    Anmerkung: zeige() greift nur auf statische Elemente zu und kann (sollte) daher selbst statisch sein. (Aufruf dann über Schaf::zeige())
    Wenn du später in komplizierteren Programmen an irgendeiner Stelle bist, wo grade kein konkretes Schaf greifbar ist, kannst du dadurch trotzdem die Frage stellen, wie viele Schafe es gibt 🙂

    PS (nicht für den OP gedacht): Bevor jetzt irgendjemand kommt mit "man kann den Destruktor manuell aufrufen": Ich weiß. Technisch ist das möglich. Man muss dann aber auch ein placement new auf den Speicherbereich aufrufen, um beim zweiten Dtor-Aufruf beim Verlassen des Scopes undefiniertes Verhalten zu vermeiden. Das wäre aber nur technisch ok. Semantisch widerspräche das immernoch der allgemeinen Auffassung von Objekt-Lebensdauern und wäre daher bestenfalls ein fieser Hack, unschön, ätzend und nicht zu empfehlen. Schon garnicht einem Rookie wie dem OP 😉



  • Hi!

    Danke für die Hilfe!

    Noch eine Frage 🙂

    int i = 1;
    
        while(i-->0){
    
        cout <<endl <<"ich muss noch " << i <<"mal lernen";}
    
        cout <<"Geschafft";
    

    Warum wird diese Schleife ausgeführt?

    Wird dann zuerst i verglichen, ob es größer ist und dann mit dem Operator -- verkleinert, oder wie ist das?

    wenn ich direkt nach dem Ablauf gehe (so stelle ich mir das zumindest vor, dass das der Ablauf ist ;-)) wird gerechnet i -1 und dann verglichen ob das Ergebnis größer als 0 ist. Aber dem ist anscheinend nicht so?

    Danke!

    Viele Grüße



  • JamBoo schrieb:

    wenn ich direkt nach dem Ablauf gehe (so stelle ich mir das zumindest vor, dass das der Ablauf ist ;-)) wird gerechnet i -1 und dann verglichen ob das Ergebnis größer als 0 ist. Aber dem ist anscheinend nicht so?

    Gratulation, Du hast gerade den Unterschied zwischen dem Postdekrement-Operator und dem Prädekrement-Operator entdeckt. 😉

    Probier mal sowas aus:

    int a=1;
    int b=1;
    cout << --a;
    cout << b--;
    


  • Danke!

    Durch solche Ausgaben bin ich auf oben stehenden Quellcode gekommen. 🙂

    bei cout << b-- wird ja zuerst b gelesen und dann vermindert. Zuerst kommt cout, dann b (b wird ausgegeben) dann wird vermindert

    bei while(b-- >0) wird ja zuerst b, dann -- und dann der Vergleichsoperator gelesen.
    Das versteht ich noch nicht so ganz. Ist das dann nicht so, dass zuerst cout dann b dann -- gelesen wird, also von links nach rechts, sondern:

    bei Postfixnotationen wird zuerst die Vergleichsoperation oder was auch immer durchgeführt und dann vermindert oder erhöht?

    Und bei Präfixnotationen wird zuerst vermindert oder erhöht und dann der jeweilige Verleich oder was auch immer durchgeführt?

    Danke!!

    Viele Grüße



  • JamBoo schrieb:

    bei while(b-- >0) wird ja zuerst b, dann -- und dann der Vergleichsoperator gelesen.

    Nein, das stimmt nicht ganz. b-- > 0 ist ein Vergleichsausdruck, der zwei Unterausdrücke hat, nämlich b-- und 0. Die werden vor dem Vergleich ausgewertet.
    Die Auswertung von b-- bewirkt, dass b dekrementiert wird und dann der alte Wert von b (nämlich 1) zurückgegeben wird, d.h. in den Vergleichsausdruck eingesetzt wird.
    d.h. da steht dann 1 > 0.
    Es wird nicht nach dem dekrementieren von b nochmal geschaut, welchen Wert b denn dann hat - das würde den Nutzen des Postdekrements völlig zerstören 😉



  • manni66 schrieb:

    So:
    [...]

    Da müsste noch ein Kopierkonstruktor hin, der auch Schafe zählt.



  • Hiesse das hier nicht Clon-Construktor? *g*

    #include <iostream>
    
    using namespace std;
    
    class Schaf {
    
       private:
          static int zaehler;
       public:
          Schaf() {zaehler++;} 
          Schaf(const Schaf &) {zaehler++;} 
          ~Schaf() {zaehler--;} 
    
          void zeige() {cout <<"Schafe:" <<zaehler <<endl;}
    };
    
    int Schaf::zaehler=0;
    
    int main(int argc, char *argv[])
    {
        Schaf s2;
        {
          Schaf s1;
          s1.zeige();
          {
            Schaf dolly(s1);
            dolly.zeige();
          }
        }
    
        s2.zeige();
    
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    

Anmelden zum Antworten