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 ; }#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 1Hanns
-
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.