Warum wird hier der Destruktor aufgerufen?



  • bei meinem Test-Programm wird der Destruktor aufgerufen, obwohl ich das nicht möchte. Woran liegt das?
    ( DIe open-Fehler sind weil ich nciht alle notwendigen Paramter gestetz habe. der Destruktor- effekt ist auch mit Open-Erfolg der Gleiche)

    #include <iostream>
    #include "btrieveClass.hh"
    
    using namespace std;
    
    /*******************************************
    **  die hauptroutine                       *
    *******************************************/
    int main() {
            cout << "================" << endl << "öffne Test" << endl;;
            btrieve test;
            // ....
            cout << "öffne test " <<  ( test.open()? "ok": "fehler") << endl;
    sleep(3);
            //------ a----
            cout << endl<<"öffne a mit pfad und datei" <<endl;
            btrieve a= btrieve("/labor/nuk/","ARZT.BTR");
            cout << (a.open()?"ok":"fehler")<<endl;
    sleep(3);
            // -----b------
            btrieve b= btrieve("/labor/nuk/","ROUTINEN.BTR");
            cout << (b.open()?"ok":"fehler")<<endl;
            sleep ( 5 );
    
            cout << "schließe test "  <<(test.close()?"ok":"fehler")<<endl;
    return 0 ;
    }
    

    btrieveClass.cc

    #include <iostream>
    #include <string>
    #include "btrieveClass.hh"
    #include "btrapi.h"
    #include "btrconst.h"
    
    using namespace std;
    
    int btrieve::idCount = 0;     // in btrieveClass.hh als static int erklärt
    
    // konstruktor mit Datenpfad und dateinamen
    // ***************************************
    btrieve::btrieve( string neuerpfad, string neuername){
            btrieve();
            setDatenpfad ( neuerpfad);
            setDateiname ( neuername);
            m_btrieveFile = neuerpfad + neuername;
    }
    
    // *********************************************
    // allgemeinder Konstruktor
    // *********************************************
    btrieve::btrieve () {
            // ....
            clientId.threadID = ++idCount ;     // Struct in .hh deklariert
    cout << "client.threadId "<< clientId.threadID<< endl;
    }
    
    btrieve::~btrieve(){
    cout << "destruktor threadId " << getThreadId ()<<endl;
            close();
    }
    
    BTI_WORD btrieve::getThreadId(){
            return clientId.threadID;
    }
    
    // ....
    

    Und das Ergebnis

    ================
    öffne Test
    client.threadId 1
    ..... goTop-Fehler :22 // ist ok
    öffne test fehler // dito

    öffne a mit pfad und datei
    client.threadId 2
    destruktor threadId 2 // wieso hier der DESTRUKTOR ??????
    ..... goTop-Fehler :6
    fehler
    client.threadId 3
    destruktor threadId 3 // und hier ???????????
    ..... goTop-Fehler :22
    fehler
    schließe test ok
    destruktor threadId 0 // und warum 2x die Id 0, die es eigentlich nicht gibt??
    destruktor threadId 0
    destruktor threadId 1

    Hanns



  • Weil du zunächst lokale Instanzen erstellst, die dann in a und b kopiert werden
    und danach zerstört werden.



  • Das verstehe ich nicht, kannst Du dazu etwas mehr sagen?
    Danke Hanns



  • Okay, also sehen wir uns das mal genauer an:

    HannsW schrieb:

    btrieve a= btrieve("/labor/nuk/","ARZT.BTR");
    

    Du möchtest eine Instanz von a anlegen und diese mit den Werten "/labor/nuk/"
    und "Arzt.BTR" initialisieren. So wie du es gemacht hast werden zunächst
    zwei Instanzen erstellt. Zum einen a und zum anderen die namenlose rechte
    Instanz, die du mit den Werten initialisierst. Dann wird der Inhalt von
    der rechten nach a kopiert. Und zu guter letzt die rechte Instanz gelöscht,
    denn sie wurde ja nur in dieser Zeile gebraucht.

    Du musst dir deutlich machen, dass "btrieve("/labor/nuk/","ARZT.BTR")" der
    Aufruf des Konstruktors ist, genauso wie "betrieve a"

    Wenn du das verhindern willst, dann schreib einfach:

    btrieve a("/labor/nuk/","ARZT.BTR");
    


  • Ja, aber nun scheint ähnliches zu passieren, wenn ich den "Parameter"-constructor aufrufe, wird sofort wieder der destruktor aufgerufen.Vermutlich durhc das erneute "btrieve()". muss ich in jedem Konstruktor eine Funktion "init()" schreiben, um die allgemeinen init-aktionen durchzuführen, die für alle gleich sein soll ?

    btrieve::btrieve( string neuerpfad, string neuername){
            btrieve();                  // RUFE DIE INIT AUF ist hier gemeint !!!
            setDatenpfad ( neuerpfad);
            setDateiname ( neuername);
            m_btrieveFile = neuerpfad + neuername;
    }
    
    // *********************************************
    // allgemeinder Konstruktor
    // *********************************************
    btrieve::btrieve () {
            m_isOpen                = false;
            m_eof           = true;
            m_bof           = true;
            m_found         = false;
            m_seekExact     = false;
            m_datenpfad     = "";                   // müsste eigentlich das aktuelle Verzeichnis zein,
                                                    // oder ne umgebungsvariable
            m_dateiname     = "";
            m_btrieveFile   = "";
            m_keyNum        = 0;                    // auf den ersten Index setzen
            m_dataLen       = 255;
            clientId.threadID = ++idCount ;
    cout << "client.threadId "<< clientId.threadID<< endl;
    }
    


  • in einem Konstruktor einen anderen aufzurufen kommt mir sehr eigenartig vor. Vermutlich erzeugt das ein temporäres Objekt, das nie benutzt und sofort wieder zerstört wird, hat aber wohl nicht den Effekt, den du erwartest. Du solltest im C++-Buch deiner Wahl dir mal das Konzept der Initialisierungsliste anschauen, das dürfte an dieser Stelle deutlich besser passen.



  • pumuckl schrieb:

    Vermutlich erzeugt das ein temporäres Objekt, das nie benutzt und sofort wieder zerstört wird

    Genau.

    In einem Konstruktor einen anderen überladenen Konstruktor aufzurufen, wie das z.B. in Java gemacht wird, ist in C++ nicht möglich.


Anmelden zum Antworten