Fehler bei vector of object



  • Hallo,

    ich habe folgendes Problem. Hab für eine Projektarbeit einen Prototypen einer Klasse für die Auflistung von Flugzeugen programmiert. Dabei speicher ich die Flugzeuge in einen Vektor. Dies funktioniert auch wunderbar, aber bei Ausführung muss ich feststellen,dass mein Objekt einmal konstruiert und mind. 3mal zerstört wird und am Ende trotzdem noch vorhanden ist. Meine Frage ist, warum wird mein Destruktor mind. einmal aufgerufen?

    Klasse:

    // airplane.h
    
    #pragma once	//verhindert doppelte Benennung
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class airplane {
       private:
     //++++++Flugzeugeigenschaften++++++++++
            string name1;
            short name2;
            short sprit;
            short type;
            short priority;
            short position;
             short anzahl;
        public:
     //+++++++Funktionen+++++++++++++++++++++
    		airplane(string gesellschaft,short flugnummer,short typ,short tank){     //Konstruktor
                    name1=gesellschaft;
                    name2=flugnummer;
                    type=typ;
                    sprit=tank;
                    priority=1;
                    position=0;
                    cout <<"Flugzeug initialisiert"<<endl;
                    anzahl++;
            }
    		airplane(const airplane &c){		//Copy-Constructor
    				name1=c.name1;
    				name2=c.name2;
    				type=c.type;
    				sprit=c.sprit;
    				priority=c.priority;
    				position=c.position;
    		}						
            ~airplane(){                                  //Destruktor
    			cerr<<"destruktor"<<endl;					
                cout<<"Flugzeug wurde zerstoert"<<endl;
                anzahl--;
            }
            void sarten(){
                position=3;
                return;
            }
            short landen(short permission,short maxlength){
                position=1;
                if(sprit<=300)priority=2;    //Prioritäten setzten ->Rangfolge der Dringlichkeit
                if(sprit<=250)priority=3;
                if(sprit<=200)priority=4;
                if(sprit<=150)priority=5;
                if(sprit<=90)absturz();
                if(permission==1){
                    cout<<"Flug"<<name1<<"-"<<name2<<"landet"<<endl;
                    position=2;
                }
                return priority;
            }
            void absturz(){
                cout << "Flug"<<name1<<"-"<<name2<<"ist abgestuerzt"<<endl;
                this->~airplane();
                return;
            }
            void umleiten(){
                cout << "Flug"<<name1<<"-"<<name2<<" wurde umgeleitet"<<endl;
                this->~airplane();
                return;
            }
    		void anzeigen(){
    			cout <<endl<< "Flug "<<name1<<"-"<<name2<<" Typ: "<<type<<" Tank: "<<sprit<<endl;
    			cout<<"aktuelle Position: ";
    			switch(position){
    				case 1:
    					cout <<"Landeanflug-Warteschlange"<<endl;
    					break;
    				case 2:
    					cout <<"Rollfeld"<<endl;
    					break;
    				case 3:
    					cout <<"Start-Warteschlange"<<endl;
    					break;
    				default:
    					cerr<<"unbekannt"<<endl;
    					break;
    			}
    		}
    
    };
    
    main:
    #include "stdafx.h"
    #include "C:\Users\Stephan\Documents\Visual Studio 2005\Projects\airplane\airplane\airplane.h"
    #include <iostream>
    #include <vector>
    #include <string>
    #include <cstdlib>
    
    using namespace std;
    
    int main()
    {
        string gesellschaft = "LH";
        short flugnummer=1256,sprit=400,typ=747,i=0;
    	unsigned int k=0;
        vector <airplane> flugzeugschleife;
    	//flugzeug.resize(k,airplane::airplane(gesellschaft,(flugnummer+i),typ,(sprit-10*i))); Alternative
    	while(i<5){
    		flugzeugschleife.resize((1+i),airplane::airplane(gesellschaft,(flugnummer+i),typ,(sprit-10*i)));
    		//flugzeug.push_back(airplane(gesellschaft,(flugnummer+i),typ,(sprit-10*i))); Alternative
    		i++;
        }
    	for(i=0;i<5;i++) flugzeugschleife[i].anzeigen();
    	flugzeugschleife[i-1].~airplane();
    	for(i=0;i<4;i++) flugzeugschleife[i].anzeigen();
    	system("Pause");
        return 0;
    }
    


  • Poste bitte deinen Code nochmals mit cpp Tags. Sonst kann dein Code kaum jemand lesen.

    Wenn du deine Objekte in den Vektor tust, dann werden die Objekte kopiert, d.h. es wird der Copy Constructor aufgerufen. Schreibe dort mal sowas wie

    cout << "Copy constructor called" << endl;
    

    Dann solltest du sehen (ich hab mir jetzt den Code nicht genau angesehen, da man ihn so kaum lesen kann) , dass gleich oft ein Objekt erzeugt wie zerstoert werden.



  • Du hast zwei konzeptionelle Fehler in deinem code.
    Erstmal weißt du gar nicht wie oft der copy-ctor auferufen wurde. Das gibt nämlich keine Meldung aus.
    Dann rufst du den Destruktor explizit auf. Warum machst du sowas? Das ist in dem gegebenen Fall absoluter Schwachsinn. Wenn du den Destruktor 2 mal explizit aufrufst, kommt dann natürlich auch 2 mal die Meldung "Flugzeug wurde zerstoert". Und noch ein drittes mal, wenn das entsprechende Objekt von "airplane" zerstört wird, weil das ja wieder einen automatischen Destruktor-Aufruf zur Folge hat.

    Kurz gesagt, schlag dir sowas

    this->~airplane();
    

    oder sowas

    flugzeugschleife[i-1].~airplane();
    

    aus dem Kopf. Wofür du das auch immer gemacht hast.



  • sorry, habs beim ersten Mal etwas vercheckt. Hab

    cout << "Copy constructor called" << endl;
    

    eingefügt und zumindest erkannt, dass mehrere Objekte kopiert werden und diese dann bis auf eines wieder gelöscht werden. Ich kann mich aber nicht erinnern, mehr als ein Objekt pro Schleifendurchgang erstellt zu haben. Liegt das daran, dass an meinem ...resize((1+i),..) [Zeile 18]?

    // airplane.h
    
    #pragma once //verhindert doppelte Benennung
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class airplane {
    private:
    //++++++Flugzeugeigenschaften++++++++++
    string name1;
    short name2;
    short sprit;
    short type;
    short priority;
    short position;
    short anzahl;
    public:
    //+++++++Funktionen+++++++++++++++++++++
    airplane(string gesellschaft,short flugnummer,short typ,short tank){ //Konstruktor
    name1=gesellschaft;
    name2=flugnummer;
    type=typ;
    sprit=tank;
    priority=1;
    position=0;
    cout <<"Flugzeug initialisiert"<<endl;
    anzahl++;
    }
    airplane(const airplane &c){ //Copy-Constructor
    name1=c.name1;
    name2=c.name2;
    type=c.type;
    sprit=c.sprit;
    priority=c.priority;
    position=c.position;
    }
    ~airplane(){ //Destruktor
    cerr<<"destruktor"<<endl;
    cout<<"Flugzeug wurde zerstoert"<<endl;
    anzahl--;
    }
    void sarten(){
    position=3;
    return;
    }
    short landen(short permission,short maxlength){
    position=1;
    if(sprit<=300)priority=2; //Prioritäten setzten ->Rangfolge der Dringlichkeit
    if(sprit<=250)priority=3;
    if(sprit<=200)priority=4;
    if(sprit<=150)priority=5;
    if(sprit<=90)absturz();
    if(permission==1){
    cout<<"Flug"<<name1<<"-"<<name2<<"landet"<<endl;
    position=2;
    }
    return priority;
    }
    void absturz(){
    cout << "Flug"<<name1<<"-"<<name2<<"ist abgestuerzt"<<endl;
    this->~airplane();
    return;
    }
    void umleiten(){
    cout << "Flug"<<name1<<"-"<<name2<<" wurde umgeleitet"<<endl;
    this->~airplane();
    return;
    }
    void anzeigen(){
    cout <<endl<< "Flug "<<name1<<"-"<<name2<<" Typ: "<<type<<" Tank: "<<sprit<<endl;
    cout<<"aktuelle Position: ";
    switch(position){
    case 1:
    cout <<"Landeanflug-Warteschlange"<<endl;
    break;
    case 2:
    cout <<"Rollfeld"<<endl;
    break;
    case 3:
    cout <<"Start-Warteschlange"<<endl;
    break;
    default:
    cerr<<"unbekannt"<<endl;
    break;
    }
    }
    
    };
    

    main

    #include "stdafx.h"
    #include "C:\Users\Stephan\Documents\Visual Studio 2005\Projects\airplane\airplane\airplane.h"
    #include <iostream>
    #include <vector>
    #include <string>
    #include <cstdlib>
    
    using namespace std;
    
    int main()
    {
    string gesellschaft = "LH";
    short flugnummer=1256,sprit=400,typ=747,i=0;
    unsigned int k=0;
    vector <airplane> flugzeugschleife;
    //flugzeug.resize(k,airplane::airplane(gesellschaft,(flugnummer+i),typ,(sprit-10*i))); Alternative
    while(i<5){
    flugzeugschleife.resize((1+i),airplane::airplane(gesellschaft,(flugnummer+i),typ,(sprit-10*i)));
    //flugzeug.push_back(airplane(gesellschaft,(flugnummer+i),typ,(sprit-10*i))); Alternative
    i++;
    }
    for(i=0;i<5;i++) flugzeugschleife[i].anzeigen();
    flugzeugschleife[i-1].~airplane();
    for(i=0;i<4;i++) flugzeugschleife[i].anzeigen();
    system("Pause");
    return 0;
    }
    


  • kleiner Troll schrieb:

    Dann rufst du den Destruktor explizit auf. Warum machst du sowas? Das ist in dem gegebenen Fall absoluter Schwachsinn. Wenn du den Destruktor 2 mal explizit aufrufst, kommt dann natürlich auch 2 mal die Meldung "Flugzeug wurde zerstoert". Und noch ein drittes mal, wenn das entsprechende Objekt von "airplane" zerstört wird, weil das ja wieder einen automatischen Destruktor-Aufruf zur Folge hat.

    Kurz gesagt, schlag dir sowas

    this->~airplane();
    

    oder sowas

    flugzeugschleife[i-1].~airplane();
    

    aus dem Kopf. Wofür du das auch immer gemacht hast.

    Habs mir vorgemerkt für später, aber momentan wird der Destruktor eben nicht explizit über die Funktionen absturz() und umleiten() aufgerufen, sonst müsste ich ja eine Meldung auf dem Bildschirm sehen. Die Zeile mit

    flugzeugschleife[i-1].~airplane();
    

    war für mich nur ein Test, um am Ende zu sehen, welches Objekt zuerst abgebaut wird. Das Problem liegt vielmehr in meiner while-Schleife. Dort werden mehr Objekte erzeugt, als ich eigentlich brauche und dann gleich wieder zerstört ->Sinn? Ich hab keine Ahnung wie ich das angestellt habe, aber ich glaube, dass hängt mit der Vektor-Funktion zusammen.



  • Opikividi schrieb:

    Die Zeile mit

    flugzeugschleife[i-1].~airplane();
    

    war für mich nur ein Test, um am Ende zu sehen, welches Objekt zuerst abgebaut wird. Das Problem liegt vielmehr in meiner while-Schleife. Dort werden mehr Objekte erzeugt, als ich eigentlich brauche und dann gleich wieder zerstört ->Sinn? Ich hab keine Ahnung wie ich das angestellt habe, aber ich glaube, dass hängt mit der Vektor-Funktion zusammen.

    *seufz*
    Ok, du hast glaube ich völlig mißverstanden was für einen Zweck der Destruktor hat. Irgendwie scheinst du anzunehmen, das ein Objekt (in dem Fall ein "airplane") zerstört wird, wenn du den Destruktor aufrufst. Es ist andersrum. Nicht "Destruktor wird auferufen => Objekt wird zerstört" sondern "Objekt wird zerstört => Destruktor wird aufgerufen".

    Um mal auf deinen konkreten Fall einzugehen: Ja, ein vector erstellt und zerstört hin und wieder Objekte. Vorallem dann, wenn er größer wird. Neuen, größeren Speicher anfordern -> Alte Objekte in neuen Speicher kopieren (mit copy-ctor) -> Alte Objekte aus altem Speicher entfernen (was dann den Destruktor aufruft).

    Wenn du das Objekt, das an letzter Stelle im vector ist, zerstören willst, mach btw einfach

    flugzeugschleife.pop_back();
    

    . Dann ist das Flugzeug auch tatsächlich weg. Und falls du nur Informationen übers Flugzeug willst, schreib dir eine info-Funktion, die Daten übers Flugzeug ausgibt, und ruf die auf. So ziemlich alles bloß nicht den Destruktor. Dafür ist er nicht da, der hat seine eigene Aufgabe.

    Ich bin mir übrigens nicht ganz sicher, ob das folgende wirklich das macht, was du glaubst.

    for(i=0;i<5;i++) flugzeugschleife[i].anzeigen();
    flugzeugschleife[i-1].~airplane();
    

    Das ist reines Glück, dass das hier nicht direkt abstürzt - oder schlimmeres. Der Grund warum es funktioniert, ist das

    flugzeugschleife[i-1]
    

    das "i" nimmt, das du hier

    short flugnummer=1256,sprit=400,typ=747,i=0;
    

    erstellt und hier

    while(i<5){
      /...
      i++;
    }
    

    auf 5 erhöht hast.


Anmelden zum Antworten