Anfängerfragen
-
daddy_felix schrieb:
kamelkacke schrieb:
Wegen dem karteileichentip.
ok. Und was passiert, wenn du es mit
vector <account> kundenliste (0);
versuchst?
Die Antwort wird wohl nicht die sein, die du gern lesen würdest (glaub ich)... aber es passiert genau das selbe wie mit 5.
-
EinerVonUns schrieb:
Hat jemand mal die zeitliche Verteilung des Auftretens von blurry und kamelkacke wissenschaftlich untersucht?
blurry trollt im Javaforum rum und ist sicher nicht kamelkacke. dafür ist blurry in seinem auftreten viel zu ignorant gegenüber nachfragen.
-
kamelkacke schrieb:
Die Antwort wird wohl nicht die sein, die du gern lesen würdest (glaub ich)... aber es passiert genau das selbe wie mit 5.
Irgendwie glaube ich dir das nicht. Sicherlich lügst du nicht mit Absicht, aber vermutlich machst du mindestens noch was anderes falsch. Oder es wird aneinander vorbei geredet. Da der Thread schon eine Weile geht:
Zeig mal den aktuellen Code -> http://www.c-plusplus.net/forum/304133
Beschreib genau, um welchen Fehler es gerade geht -> http://www.c-plusplus.net/forum/200753
-
Kann es sein, dass du in "account" dynamisch Speicher holst und diesen im Destruktor freigibst?
In dem Fall hast du vermutlich die "Rule of three" (-> Google) verletzt...
-
Also ich trolle nicht rum.. ich hab seit 2 Tagen nur diesem Code im Kopf..
Hier mal der gesamte Code. Er ist echt simpel.
1. Eine Klasse die einige Zeilen in Anspruch nimmt aber nur aus einem Konstruktor besteht, paar Variablen die im Konstruktor definiert werden, einem destruktor und einer zeigedaten funktion.
2. Eine sehr kurze Klasse die komplett Baustelle ist. Aber selbst wenn ich keine Instanz von ihr erstelle, passiert das worüber ich ganze Zeit rede.
3. <<operator überlader, der auch mist ist, aber mit dem Fehler nichts zu tun haben kann....glaub ich
4. Main funktion, die zu 90% aus Menuedefinition und Ausgabe besteht.
#include <iostream> #include <string> #include <vector> using namespace std; static int kundenzaehler = 0; void personalmenue (); class account { friend class angestellter; public: account () { do { cout << "Bitte geben Sie Ihren Namen ein\n"; cin >> name; cout << "Bitte geben Sie Ihren Vorname ein\n"; cin >> vorname; cout << "Bitte geben Sie Ihren Kontostand ein\n"; cin >> kontostand; do { cout << "Bitte Ihre Wunschgeheimzahl eingeben (4 Ziffern)\n"; cin >> geheimzahl; } while (geheimzahl >= 10000 || geheimzahl <= 999); cout << "Sind die eingegebenen Daten korrekt?\n\n"; cout << "Vorname : " << vorname << endl; cout << "Name : " << name << endl; cout << "Kontostand : " << kontostand << endl; cout << "Geheimzahl : " << geheimzahl << endl << endl; cout << "(1) Ja" << endl; cout << "(2) Nein" << endl; cin >> bestaetigung; } while (bestaetigung != 1); cout << "Ihr Bankkonto wurde erstellt"; kundenzaehler++; kundenid = kundenzaehler; cout << "Aktuell hat die Bank " << kundenzaehler << " Kunden\n\n"; } ~account () { kundenzaehler--; cout << "Ihr Bankkonto wurde erfolgreich geloescht\n" "Das Geld behalten wir allerdings\n" "Schoenen Tag noch\n"; } int bestaetigung; void zeigedaten () { cout << "Ihre aktuellen Daten sind:\n\n"; cout << "Vorname : " << vorname << endl; cout << "Name : " << name << endl; cout << "Kontostand : " << kontostand << endl; cout << "Geheimzahl : " << geheimzahl << endl << endl; } private: string name; string vorname; int geheimzahl; long long kontostand; int kundenid; }; class angestellter { public: angestellter () { cout << "";} ~angestellter () { cout << "Angestellter geloescht"; } void transfer (account *cash, account *cash2, account *id1, account *id2) { cout << "bla"; } void kundendaten () { cout << "test"; } void kundenloeschen () { cout << "test"; } private: account *paccount1; account *paccount2; account *pid1; account *pid2; }; ostream& operator << (ostream& os, account const& a) { os << a.bestaetigung; return os; } int main () { int auswahl = 0; angestellter personal; vector <account> kundenliste (0); vector <account> :: iterator i; do { cout << "Willkomen bei der Mr.Nice International Bank AG..\n\n" "Menueauswahl:\n" "(1) Neues Konto erstellen\n" "(2) Einloggen\n" "(3) Konto aufloesen\n" "(4) Beenden\n"; cin >> auswahl; if (auswahl == 1) { cout << "Neues Konto wird erstellt..\n"; account kunde; kundenliste.push_back (kunde); for (i=kundenliste.begin (); i!=kundenliste.end (); i++) { cout << *i << endl; } } else if (auswahl == 2) { cout << "Einloggen\n\n"; } else if (auswahl == 3) { cout << "Konto wird geloescht\n\n"; } else if (auswahl == 4) { cout << "Vielen Dank fuer Ihren Besuch\n" "Beehren Sie uns bald wieder"; } else if (auswahl == 123454321) { personalmenue (); } else { cout << "Ungueltige Eingabe\n\n"; } } while (auswahl != 4); } void personalmenue () { int personalauswahl = 0; do { cout << "Personalmenue\n\n" "(1) Ueberweisungen taetiegen\n" "(2) Konto loeschen\n" "(3) Kundenanzahl ausgeben\n" "(4) Einzelne Kundendaten ausgeben\n" "(5) Alle Kunden ausgeben\n" "(6) Beenden\n"; cin >> personalauswahl; if (personalauswahl == 1) { cout << "Banktransfer\n"; } else if (personalauswahl == 2) { cout << "Konto loeschen\n"; } else if (personalauswahl == 3) { cout << "Momentan befinden sich " << kundenzaehler << " in der Datenbank\n\n"; } else if (personalauswahl == 4) { cout << "Einzelne Kundendaten ausgeben\n\n"; } else if (personalauswahl == 5) { cout << "Alle Kundendaten ausgeben\n\n"; } else if (personalauswahl == 6) { cout << "Personalprogramm wird beendet\n\n"; } else { cout << "Ungueltige Auswahl\n\n"; } } while (personalauswahl != 6); }
-
Und was genau ist das Fehlverhalten?
Meine Fresse, dir muss man echt jeden Schei** aus der Nase ziehen

-
Da sind sowohl die 5 leeren Unsinnsinstanzen drin, von denen du gesagt hast, dass du sie weg gemacht hast, als auch, wie von daddy_felix vermutet, gleich mehrere Verletzungen der Regel der großen Drei. Das heißt, trotz mangelnder Fragestellung (siehe Beitrag von otze) haben die Helfer sogar richtig geraten. Trotz ihrer Antworten sind aber genau diese Fehler noch da. Die Regel der großen Drei kann ich ja verstehen, das ist für Anfänger nicht einfach*. Aber die 5 Instanzen im vector nach mehrmaligem Hinweis?
Dein Klassendesign ist sehr merkwürdig. Konstruktor und Destruktor einer Klasse sind nicht vergleichbar mit dem Konzept einer Kontoeröffnung oder -schließung. Der Rest der Klassengestaltung ist auch nicht so toll, aber da andere Baustellen gerade dringender sind (immer noch die 5 Instanzen!) lasse ich mich dazu mal nicht groß aus.
*: Und ausgerechnet Anfänger scheinen magisch das Bedürfnis zu verspüren, ihre Klassen so zu gestalten, dass sie die Regel der großen Drei benötigen. Ich kann mich kaum erinnern, wann ich das letzte Mal wirklich produktiv einen selbstdefinierten Destruktor geschrieben habe.
-
Oh man sry sry. Das Problem ist:
1. dass statt der Menueausgabe direkt eine Instanz erzeugt wird.
2. dass die Instanz direkt gelöscht wird.Zu Sepp die war 5 da weil ich nochmal geguckt habe ob sich das Vehalten nicht doch irgendwie anders bemerkmbar ist. Also ob ich was übersehen habe. Was leider nicht der Fall ist.
-
kamelkacke schrieb:
1. dass statt der Menueausgabe direkt eine Instanz erzeugt wird.
2. dass die Instanz direkt gelöscht wird.Die Antworten da drauf sind immer noch die gleichen, die schon mehrmals gegeben wurden. Ob mit oder ohne 5, so ist immer noch die Korrespondenz Kontoeröffnung/schließung <-> Konstruktor/Destruktor nicht zum Klassenkonzept von C++ passend (mit etwas Drücken kann man es vielleicht da rein quetschen, aber es wird nicht gut) und selbst wenn, dann wurde es technisch falsch umgesetzt (Regel der großen Drei).
-
Nagut dann lass ixh mi das nochmal alles auf der Zunge sergehen. Vielen Dank an alle für eure Geduld und Einsatz!!
-
Erzeugt dieser code Speicherleaks oder gibts sonst irgendwas daran auszusetzen? Ausser die großen drei.
#include <iostream> #include <string> #include <list> using namespace std; string a = "ä"; string o = "ö"; string u = "ü"; class musssein { private: int id; public: musssein (int idparam) { cout << "Raumschiff wird erstellt!\n"; id = idparam; } ~musssein () { cout << "Raumschiff wird gel" << o << "scht\n"; } void starten () { cout << "Raumschiff " << name << " mit der ID " << id << " startet\n"; } }; int main () { int anzahl = 0; list <musssein*> lmusssein; list <musssein*> :: iterator i; musssein *temp; cout << "Anzahl der zu erstellenden Schiffe eingeben\n"; cin >> anzahl; for (int j; j<anzahl; j++) { temp = new musssein (j+1); lmusssein.push_back (temp); } for (i=lmusssein.begin (); i!=lmusssein.end (); i++) { (*i)->starten (); } for (i=lmusssein.begin (); i!=lmusssein.end (); i++) { delete (*i); (*i) = NULL; } }
-
Abgesehen davon, dass der Code nicht compiliert (Zeile 30):
Geht sofort los mit globalen Variablen (natürlich total sinnlose Funktion dieser Variablen), danach eine Klasse mit einem Unsinnsnamen, dann kommen ohne Grund Zeiger in die Liste (vermutlich, weil du wohl immer noch nicht verstanden hast, wieso deine Instanzzähler nicht funktionieren. Teufel mit Belzebub ausgetrieben), eine komische Wahl des Containers, unpassender Scope der zudem unnötigen Variable "temp" (der Name allein reicht schon, um zu wissen, dass sie unnötig ist), uninitialisierte Variablen, und als krönender Abschluss hast du wohl irgendwo Code abgeschrieben, in dem Zeiger auf NULL gesetzt werden, ohne zu verstehen, wieso dies getan wurde (damit bist du aber immerhin in guter Gesellschaft, dies ist wohl einer der häufigsten Fehler bei der Benutzung von Zeigern).
Das das ganze Speicher leckt im Fall einer Exception fällt da kaum mehr auf.Ein paar oberflächliche Korrekturen der schlimmsten Fehler:
#include <iostream> #include <vector> using namespace std; class Raumschiff { private: int id; public: explicit Raumschiff (int idparam) : id(idparam) { cout << "Raumschiff wird erstellt, id = " << id << '\n'; } ~Raumschiff () { cout << "Raumschiff wird gelöscht, id = " << id << '\n'; } Raumschiff (const Raumschiff & other) : id(other.id) { cout << "Raumschiff wird kopiert, id = " << id << '\n'; } void starten () { cout << "Raumschiff mit der ID " << id << " startet\n"; } }; int main () { vector <Raumschiff> raumschiffe; cout << "Anzahl der zu erstellenden Schiffe eingeben\n"; int anzahl; cin >> anzahl; for (int i = 0; i<anzahl; i++) { raumschiffe.push_back(Raumschiff(i+1)); } for (vector<Raumschiff>::iterator i=raumschiffe.begin(); i != raumschiffe.end (); ++i) { i->starten (); } }http://ideone.com/noFFkw
Vielleicht geht dir beim Ausführen auch endlich ein Licht auf, wieso deine Instanzenzähler nie funktionierten.Ich habe auch noch SEHR viele Kleinigkeiten korrigiert, die ich nicht weiter erwähnt habe, vergleich am besten mal Zeile für Zeile, was anders ist und überleg, warum ich das wohl so gemacht habe. Achte auch auf vermeintliche Kleinigkeiten.
-
Gold. Hab mal das Kapitel Kopierkonstruktor meines Buches mal gelesen und unter "In ferner Zukunft brauch ich das mal.." abgehackt. Keine Ahnung warum. Ansonsten danke für die perfektionierung. Werde es mir gleich verinnerlichen. Danke!
-
Hey, drei Fragen zu Seppjs letzten Beitrag, oberhalb seines geposteten posts:
1. Was spricht dagegen, einen zeiger mit NULL zu initiieren? Hab gelesen, dass man das macht, um unvorhergesehene ereignisse zu unterbinden (undefined behavior glaub ich).
2. Wenn keine exception vorliegt, wird bei new, delete kein speicher geleaked, richtig?
Unabhängig von Seppjs post:
3. Was habt ihr alle gegen new und delete?
Edit:
4. Falls trotzdem eine exception auftreten sollte, koennte man das doch mit try&catch oder assert abfangen oder dient das nur zur Fehlersuche?
5. Was ist eine superklasse? Eine klasse von der geerbt wird?
-
new & delete müssen als solches balanciert für jeden Speicherblock auftreten, ansonsten gibt es einen Leak. Um die Balancierung zu gewähren, benötigt es die entsprechende Aufmerksamkeit und es können einem leicht Fehler in den abstrusesten Randfällen unterlaufen.
Das alles vor dem Hintergrund, dass die Benutzung selten Not tut, weil es für die überwiegenden Fälle robuste, fertige Klassen gibt, die einem zusammen mit den Lebenszeit-Regeln von C++ Sicherheit "garantieren".
Aber auch wenn man der perfekte new&delete-Roboter ist, so würde der Verwaltungscode und die Fehlerbehandlung den eigentlich interessanten Teil des Codes inaktzeptabel verrauschen, wenn man den nicht auslagert und somit das Rad neu erfindet.
-
Kurze Zwischenfrage: Warum hast du den Konstructor explicit gemacht?
-
Ruvi++ schrieb:
Kurze Zwischenfrage: Warum hast du den Konstructor explicit gemacht?
um implizite Konversionen von int nach Raumschiff zu verhindern.
-
daddy_felix schrieb:
Ruvi++ schrieb:
Kurze Zwischenfrage: Warum hast du den Konstructor explicit gemacht?
um implizite Konversionen von int nach Raumschiff zu verhindern.
Entschuldige, irgendwie steh ich auf dem Schlauch.
Wie kann das denn in dem geschriebenen Code passieren?
Ich uebergebe doch einfach einen int Parameter als Argument an den Konstruktor der damit eine interne Variable initialisiert?
-
Damit verhindert SeppJ sowas:
std::vector<Raumschiff> v; v.push_back( 1 );Taucht im Code so zwar nicht auf, aber wer weiß, was TE noch so alles vorhat.
-
Ruvi++ schrieb:
Wie kann das denn in dem geschriebenen Code passieren?
Ganz einfach:
void foo( Raumschiff );Nun ist es möglich, foo mit 4 als Argument aufzurufen. Das ist aber definitiv nicht wünschenswert, da wir ja wollen, dass im Code explizit steht, dass das Argument ein
Raumschiffinitialisiert.Edit: Zu spät.