Wie kann ich eine laufende Nummer in einer Klasse realisieren?
-
Hallo,
das Problem ist folgendes:
Mein Prof hat eine Anwendung geschrieben die sich auf eine Klasse bezieht. Ich darf diese Klasse schreiben und kriege es micht hin.Er sagt:
#include <iostream> #include "kunde.h" using namespace std; int main(void) { CKunde kunde[8]; CKunde neuKunde1, neuKunde2; unsigned long kdnr; int i; for(i=1; i < 8; i ++) kunde[i].anlegen(); cout << "Liste aller bisherigen Kunden:" << endl; for (i=1; i < 8; i++) cout << kunde[i].getKdnr() << endl; kunde[2].loeschen(); kunde[5].loeschen(); neuKunde1.anlegen(); neuKunde2.anlegen(); cout << "Liste aller aktuellen Kunden" << endl << "(nach Loeschen und Anlegen zweier neuer Kunden):" << endl; for (i=1; i < 8; i++) if (kdnr = kunde[i].getKdnr()) cout << kdnr << endl; else cout << i << ": fehlt" << endl; cout << neuKunde1.getKdnr() << endl; cout << neuKunde2.getKdnr() << endl; cout << "Naechste zu vergebende Nummer: " << CKunde::getNaechstNr() << endl; system("pause"); return 0; }und erwartet als ausgabe:
Liste aller bisherigen Kunden:
1
2
3
4
5
6
7
Liste aller aktuellen Kunden
(nach Loeschen und Anlegen zweier neuer Kunden):
1
2: fehlt
3
4
5: fehlt
6
7
8
9
Naechste zu vergebende Nummer: 10Ich habe bisher:
#include <cstdlib> #include <iostream> using namespace std; class CKunde { private: int kdnr; public: CKunde anlegen(){ static int lfnr=1; CKunde *temp = new CKunde; temp->kdnr=lfnr; lfnr++; return *temp; } void loeschen(){} void getNaechstNr(){} int getKdnr(){ return kdnr; } };Ich dachte ich könnte diese laufende nummer mit static hinbekommen aber entweder es geht nicht oder ich mache es falsch. Ich kriege alle möglichen Werte gelifert aber nicht 1,2,3 wie ich es mir erträumt hatte.
Wie kann ich das am besten lösen?
-
edit:müll
-
Ich glaube eine statische Variable einer Methode ist nur verfügbar in allen Methodenaufrufen der jeweiligen Instanz. Mach die Variable mal als private statische Variable, dann soltle es gehen.
-
Wäre es nicht logischer eine Klasse Kunde zu nehmen und dafür ein Containerklasse zu schreiben?
-
@the_alien
Die Kundennummer gehört zum Kunde, denke nicht dass es gewünscht ist die Kunden-Objekte von einem Container abhängig zu machen.@username214
Das Problem ist, dass du eine Variable innerhalb einer Funktion statisch gemacht hast. Diese ist nur innerhalb der Funktion abfragbar.CKunde anlegen() { static int lfnr=1; CKunde *temp = new CKunde; :open_mouth: temp->kdnr=lfnr; lfnr++; return *temp; :confused: }Die Funktion müsste eigentlich ErzeugeSpeicherleak heissen.....
Wenn du es geschickt machen möchtest baust du die statische Variable in den Konstruktor ein und weisst den wert dort direkt zu. Dann kannst du dir die anlegfunktion sparen und hast sichergestellt, dass jeder Kunde eine eindeutige Nummer hat.
-
Was spricht gegen sowas?
class Kunde { private: static std::size_t lfdKNr; //...noch viel mehr public: Kunde() { ++lfdKNr; } //...noch viel mehr }; std::size_t Kunde::lfdKNr = 0;mfg
v R
-
@Mathias
Da hast du wohl recht aber in der Aufgabe steht das man es nicht über den Konstruktor machen soll weil sonst die Nummer auch bei temporären Objekten erhöht würde. Deswegen die anlegen()
Ähm und was ist mit Speicherleak? Wo ist der Fehler?@FireFlow
wenn ich es so mache bekomme ich Ärger mit dem Linker [Linker error] undefined reference to `CKunde::lfnr'
-
username214 schrieb:
@Mathias
Da hast du wohl recht aber in der Aufgabe steht das man es nicht über den Konstruktor machen soll weil sonst die Nummer auch bei temporären Objekten erhöht würde. Deswegen die anlegen()
Ähm und was ist mit Speicherleak? Wo ist der Fehler?Der Speicherbereich wird nicht mehr freigegeben.
@FireFlow
wenn ich es so mache bekomme ich Ärger mit dem Linker [Linker error] undefined reference to `CKunde::lfnr'Weil du die statische Variable initialisieren musst, siehe meinen Code.
mfg
v R
-
Was spricht dagegen das die Methode einen Pointer auf den Speicher zurueckgibt?
Muss man halt nur explizit erwaehnen, das wenn die Methode aufgerufen wird danach selbst aufzuraeumen ist.. Schoener waere natuerlich wenn die Klasse sich selbst merkt was man in ihr anlegt und hinterher alles was jemand mit ihr gemacht hat per d'tor wieder wegraeumt..
-
PunI$0R schrieb:
Was spricht dagegen das die Methode einen Pointer auf den Speicher zurueckgibt?
Muss man halt nur explizit erwaehnen, das wenn die Methode aufgerufen wird danach selbst aufzuraeumen ist.. Schoener waere natuerlich wenn die Klasse sich selbst merkt was man in ihr anlegt und hinterher alles was jemand mit ihr gemacht hat per d'tor wieder wegraeumt..Schau dir die Funktion nochmal genau an.
mfg
v R
-
Recht hast du. Wenn ich es initialisiere dann geht es.
Wie sieht das aus mit dem Speicherleak?
Mache ich da was grundlegend falsch oder ist es einfach weil ich kein delete im zb. destructor definiert habe?
(Sorry wegen dämlich fragen aber ich bin ziemlich neu...)
-
username214 schrieb:
Recht hast du. Wenn ich es initialisiere dann geht es.
Wie sieht das aus mit dem Speicherleak?
Mache ich da was grundlegend falsch oder ist es einfach weil ich kein delete im zb. destructor definiert habe?
(Sorry wegen dämlich fragen aber ich bin ziemlich neu...)Im DTor bringt dir das delete nichts. Aber es ist schon so, dass der Speicher-
bereich in dem von Mathias geposteten Code nicht wieder freigegeben wird. Es
wird eine Kopie der Instanz zurueckgegeben (*temp) aber der Speicher wird nicht
wieder freigegeben.mfg
v R
-
Du erstellst ein neues Objekt auf dem Heap und gibst eine __KOPIE__ davon zurück. Der Pointer wo das Objekt auf dem Heap ist, ist verloren.
-
*g* @ v R: uhh bin bischen Blind, heute..
Er sollte wohl bspw. mal den Stern ausm return nehmen und ein Array v. Pointern auf Kunden nehmen und sich seine Objekte da von der Methode reingeben lassen..waere natuerlich immer noch das probl mit dem deleten..
-
Ok, so macht man es nicht...
Kann ich es umschreiben so das es keine Speicherleaks gibt oder kann es auf die Tour nur falsch werden.
-
Wie gesagt du kannst dafuer sorgen das sich dein Objekt merkt was mit ihm an Speicher allokiert wurde..
-
Wenn es eine Methode der Klasse Kunde ist, muss sie garnix zurückgeben,
da sie ja somit zugriff auf die internen Variablen der Klasse hat.void Kunde::anlegen() { static int skdnr =0; kdnr = ++skdnr; }
-
Dabke für euere Hilfe. Ich habe das Ding fertig und es schein zu funktionieren...
#include <cstdlib> #include <iostream> using namespace std; class CKunde { static size_t zaehler; private: int kdnr; public: CKunde(){ // cout << "Konstruktor" << endl; kdnr =0; } ~CKunde(){cout<<"Destruktor"<<endl;} void anlegen(){ zaehler++; kdnr=zaehler; } void loeschen(){kdnr=0;} int getKdnr(){return kdnr;} static int getNaechstNr(){return zaehler+1;} }; std::size_t CKunde::zaehler= 0; int main(void) { CKunde kunde[8]; CKunde neuKunde1, neuKunde2; unsigned long kdnr; int i; for(i=1; i < 8; i ++) kunde[i].anlegen(); cout << "Liste aller bisherigen Kunden:" << endl; for (i=1; i < 8; i++) cout << kunde[i].getKdnr() << endl; kunde[2].loeschen(); kunde[5].loeschen(); neuKunde1.anlegen(); neuKunde2.anlegen(); cout << "Liste aller aktuellen Kunden" << endl << "(nach Loeschen und Anlegen zweier neuer Kunden):" << endl; for (i=1; i < 8; i++) if (kdnr = kunde[i].getKdnr()) cout << kdnr << endl; else cout << i << ": fehlt" << endl; cout << neuKunde1.getKdnr() << endl; cout << neuKunde2.getKdnr() << endl; cout << "Naechste zu vergebende Nummer: " << CKunde::getNaechstNr() << endl; system("pause"); return 0; } /* Erwartete Ausgabe dieses Programms: Liste aller bisherigen Kunden: 1 2 3 4 5 6 7 Liste aller aktuellen Kunden (nach Loeschen und Anlegen zweier neuer Kunden): 1 2: fehlt 3 4 5: fehlt 6 7 8 9 Naechste zu vergebende Nummer: 10 */