Anfängerfrage zu OOP



  • Hab mal ein kleines Beispiel zusammgehackt:

    #include <list>
    #include <iostream>
    using namespace std;
    
    class Kugel {
    public:
       Kugel():id(++gid) { }
       ~Kugel() { cout << "Kugel " << id << " wird geloescht" << endl; }
       int getID() const { return id; }
    private:
       int id;
       static int gid;
       };
    
    int Kugel::gid = 0;
    
    int main() { 
       Kugel k1, k2, k3;
       std::list<Kugel> l;
       l.push_back(k1);
       l.push_back(k2);
       l.push_back(k3);
       for(std::list<Kugel>::iterator it = l.begin();  it!=l.end(); ++it) 
          cout << "Kugel " << it->getID() << endl;
    
       std::list<Kugel>::iterator it = l.begin();
       ++it;
       l.erase(it);  // 2. Kugel löschen
    
       for(std::list<Kugel>::iterator it = l.begin();  it!=l.end(); ++it) 
          cout << "Kugel " << it->getID() << endl;
    
       cin.get(); 
       return 0; 
    }
    


  • Hallo,

    so ganz verstehe ich das nicht!

    Also, ich musste den code etwas modifizieren, wegen Fehlern durch Neudefinition.

    Jetzt sieht er so aus:

    #include <list> 
    #include <iostream> 
    using namespace std; 
    
    class Kugel { 
    public: 
    	Kugel():id(++gid) { } 
    	~Kugel() { cout << "Kugel " << id << " wird geloescht" << endl; } 
    	int getID() const { return id; } 
    private: 
    	int id; 
    	static int gid; 
    }; 
    
    int Kugel::gid = 0; 
    
    int main() { 
    	Kugel k1, k2, k3; 
    	std::list<Kugel> l; 
    	l.push_back(k1); 
    	l.push_back(k2); 
    	l.push_back(k3); 
    	for(std::list<Kugel>::iterator it = l.begin();  it!=l.end(); ++it) 
    		cout << "Kugel " << it->getID() << endl; 
    
        it = l.begin(); 
    	++it; 
    	l.erase(it);  // 2. Kugel löschen 
    
    	for( it = l.begin();  it!=l.end(); ++it) 
    		cout << "Kugel " << it->getID() << endl; 
    
    	cin.get(); 
    	return 0; 
    }
    

    Als Ausgabe erhalte ich:

    Kugel 1
    Kugel 2
    Kugel 3
    Kugel 2 wird gelöscht
    Kugel 1
    Kugel 3
    //jetzt muss ich was eingeben z.B
    egal

    Kugel 1 wird gelöscht
    Kugel 3 wird gelöscht
    Kugel 3 wird gelöscht
    Kugel 2 wird gelöscht
    Kugel 1 wird gelöscht

    Das kann ich mir nicht werklären!



  • Andreas XXL schrieb:

    Kugel 1
    Kugel 2
    Kugel 3
    Kugel 2 wird gelöscht
    Kugel 1
    Kugel 3
    //jetzt muss ich was eingeben z.B
    egal

    Kugel 1 wird gelöscht
    Kugel 3 wird gelöscht
    Kugel 3 wird gelöscht
    Kugel 2 wird gelöscht
    Kugel 1 wird gelöscht

    Das kann ich mir nicht werklären!

    Jo, das passt auch. Zur Ausgabe:
    Kugel 1,2,3 werden in der 1. Schleife ausgegeben.
    Dann wird Kugel2 gelöscht und deren Destruktor aufgerufen, weshalb in der
    folgenden Schleife nur noch Kugel 1 und 3 ausgegeben werden
    Nach deiner Eingabe endet main und der Gültigkeitsbereich für die Liste sowie alle Kugeln endet, weshalb sie zerstört werden (Da die Liste zuerst auf den Stack gepusht wurde, wie ihr Destruktor auch zuerst aufgerufen)



  • Hallo,

    aber warum wird Kugel 2 nochmal gelöscht, ich dachte die wär schon wiklich vorher gelöscht worden?



  • Andreas XXL schrieb:

    Hallo,

    aber warum wird Kugel 2 nochmal gelöscht, ich dachte die wär schon wiklich vorher gelöscht worden?

    Weil die Übergabe an push_back per value passiert, sprich: Die Variable wird kopiert und beim Löschen wird eben der Dtor der Kopie aufgerufen. Beim Verlassen von main wird dann das "Original" gelöscht.



  • Und wie würde ich vorher das original löschen?

    Kannst du mir auch erklären, was new free und malloc machen und warum man das hier nicht braucht?



  • Andreas XXL schrieb:

    Und wie würde ich vorher das original löschen?

    Kannst du mir auch erklären, was new free und malloc machen und warum man das hier nicht braucht?

    Ich glaube, du solltest erst noch ein paar Tutorials und Bücher durchlesen, denn call by value und call by ref sind die Basics. Ein Objekt, das sich auf dem Stack befindet kann man nicht so einfach löschen. Bei solchen Objekten wird implizit der Destruktor aufgerufen, wenn sie ihren lokalen Gültigkeitsbereich verlassen. Hier wär noch ein Beispiel mit Zeigern (hier kannst du die Lebensdauer eines Objekts selbst bestimmen):

    #include <list> 
    #include <iostream> 
    using namespace std; 
    
    class Kugel { 
    public: 
       Kugel():id(++gid) { } 
       ~Kugel() { cout << "Kugel " << id << " wird geloescht" << endl; } 
       int getID() const { return id; } 
    private: 
       int id; 
       static int gid; 
       }; 
    
    int Kugel::gid = 0; 
    
    int main() { 
       // 4 Kugeln auf dem Heap anlegen
       Kugel* k = new Kugel;
       Kugel* k2 = new Kugel;
       Kugel* k3 = new Kugel;
       Kugel* k4 = new Kugel;
       std::list<Kugel*> l; 
       l.push_back(k);   // Jetzt speichern wir Zeiger in der List
       l.push_back(k2);  // d.h, es wird der Zeiger kopiert und NICHT das ganze
       l.push_back(k3);  // Objekt
    
       for(std::list<Kugel*>::iterator it = l.begin();  it!=l.end(); ++it) 
          cout << "Kugel " << (*it)->getID() << endl; 
    
       std::list<Kugel*>::iterator it = l.begin(); 
       ++it;
       delete *it;   // Kugel 2 vom Heap löschen
       l.erase(it);  // Zeiger auf den nicht mehr gültigen Block entfernen
    
       for(std::list<Kugel*>::iterator it = l.begin();  it!=l.end(); ++it) 
          cout << "Kugel " << (*it)->getID() << endl; 
    
       // Kugel 4 löschen weil ich Bock drauf hab:
       delete k4;  // Hier wird auch der Dtor aufgerufen
    
       cin.get(); 
       return 0; 
    }
    


  • Hallo,

    ich habe das jetzt so verstanden:
    Bitte sagt mal ob jetzt alles richtig verstanden habe.

    Kugel* k = new Kugel;
    Mit new erzeugt man dynamisch neuen Speicher für die Instanz des Objektes und erhält einen Zeiger auf die Instanz.

    Mit delete k löscht man die Instanz und gibt den speicher wieder frei.
    Vorher wird der destrukor aufgerufen!

    Packt man den Zeiger in einen Vector, wird dort natürlich nur der Zeiger auf den Speicherplatz gespeichert.

    Mit delete kann man wieder die Instanz löschen. Es bleibt noch der zeiger im vector, der jetzt nur noch auf etwas zeigt, was nicht mehr da ist(weil mit delete gelöscht)
    Also löscht man mit .erase() noch diesen Zeiger

    Und alles ist gut!



  • Andreas XXL schrieb:

    Hallo,

    ich habe das jetzt so verstanden:
    Bitte sagt mal ob jetzt alles richtig verstanden habe.

    Kugel* k = new Kugel;
    Mit new erzeugt man dynamisch neuen Speicher für die Instanz des Objektes und erhält einen Zeiger auf die Instanz.

    Mit delete k löscht man die Instanz und gibt den speicher wieder frei.
    Vorher wird der destrukor aufgerufen!

    Packt man den Zeiger in einen Vector, wird dort natürlich nur der Zeiger auf den Speicherplatz gespeichert.

    Mit delete kann man wieder die Instanz löschen. Es bleibt noch der zeiger im vector, der jetzt nur noch auf etwas zeigt, was nicht mehr da ist(weil mit delete gelöscht)
    Also löscht man mit .erase() noch diesen Zeiger

    Und alles ist gut!

    Absolut richtig 👍



  • Hallo,
    ich habe noch eine Frage:

    Ich habe meine Klasse so gebaut wie die Klasse Kugel.
    Nun benutze ich in Kugel einen Stack um etwas zu berechnen.

    Komischerweise Klappt das bei der ersten Kugel gut. Aber bei der zweiten Kugel geht es nicht mehr!

    Sind dann die Stacks in den verschiedenen instanzen von kugel getrennt, oder schreiben alle Instanzen in den selben Stack?



  • Andreas XXL schrieb:

    Hallo,
    ich habe noch eine Frage:

    Ich habe meine Klasse so gebaut wie die Klasse Kugel.
    Nun benutze ich in Kugel einen Stack um etwas zu berechnen.

    Komischerweise Klappt das bei der ersten Kugel gut. Aber bei der zweiten Kugel geht es nicht mehr!

    Sind dann die Stacks in den verschiedenen instanzen von kugel getrennt, oder schreiben alle Instanzen in den selben Stack?

    Wenn sie nicht statisch sind, dann sind das individuelle Instanzen. Aber dein Design ist schlecht. Wieso sollte eine Kugel einen Stack haben? Eine Kugel hat einen Schaden, ne Geschwindigkeit, Masse etc, aber gewiss keinen Stack (mal abgesehen davon, dass Stack hier eine ungünstige Datenstruktur ist). Wenn du mehrere Kugeln verwalten willst, dann schreib lieber nen Manager (BulletManager).


Anmelden zum Antworten