016
15.03.2006, 09:13 Uhr
ao
(Operator)
|
Hallo Hans, hier ist mal mein Senf dazu.
Zitat von Hans: |
Wenn man das so dem Compiler vorsetzt, dann erhält man über 20 Fehlermeldungen.
|
Bei mir (VC 6) läuft der Code ohne Fehler durch. Die Warnungen (die nur auf höchstem Warninglevel erscheinen) betreffen Umwandlungen von double nach float und von int nach float, das unreferenzierte Label und die unreferenzierte Variable "versuche", unschön, aber in diesem Zusammenhang eher harmlos.
Du solltest vielleicht nicht gerade Borland 5.5 als Referenz für einen standard-konformen Compiler nehmen, dafür ist der nämlich etwas zu alt.
Zitat: |
Dann fällt bei den #include-Direktiven auf, das C und C++ munter gemixt wurden.
|
Das stimmt, sowas sollte man nicht machen. Man sollte sich für *eine* Lib entscheiden, Standard-C oder Standard-C++, und dabei bleiben. Zumal tatsächlich printf und cout nebeneinander benutzt werden, und das ist dem Autor dick anzukreiden.
Zitat: |
Ach ja,
steht zweimal da; wozu soll das denn gut sein?
|
Eine Nachlässigkeit, die aber nicht schadet, weil string.h normalerweise einen Include-Guard hat.
Zitat: |
Zitat von borland C++ Compiler: |
Error E2015 Schulproggy.cpp 20: Ambiguity between 'string' and 'std::string'
|
Da kommen sich also die C-Funktionen aus string.h und die C++ - Äquivalente aus std::string in die Quere... Schön. - ähh Sch****e!
|
Siehe oben. Deine nicht ganz top-aktuelle C++-Lib hat string noch nicht im Namespace std, oder sie bringt überflüssigerweise ihr eigenes "using namespace std;" mit; würde sie das richtig machen, gäbs hier keinen Fehler.
Zitat: |
Bei der Deklaration der Klasse fällt mir auf, das der Destruktor fehlt. Okay, da gibt es einen Standard-destruktor, ...
|
... mit dem man eigentlich zurechtkommt, weil die Klasse nichts hat, was besonders zu zerlegen ist.
Zitat: |
Aber dann: Der Konstruktor mit den vielen Parametern, und zwei Zeilen tiefer eine Funktion init(...) mit genau den selben Parametern. Vergleicht man die Definitionen der beiden, stellt man fest, das beides der Selbe Code ist. Anscheinend hat da jemand den Sinn von Konstruktoren nicht verstanden.
|
Vordergründig ergibt das schon Sinn. Ein Konto-Objekt kann entweder mit Parametern konstruiert werden oder default-konstruiert und dann mit Parametern initialisiert werden. Der zweite Weg wird gebraucht, wenn man ein Array von Konto-Objekten anlegt, so wie es weiter unten mit new Konto [anzahl_kunden] gemacht wird. C++ erlaubt nämlich hier nur die Verwendung des Default-Konstruktors. Daher könnte der "naive" C-Programmierer denken, dass er hier tatsächlich beides braucht. Doof ist allerdings, dass der Initialisierungs-Code kopiert wurde und jetzt an zwei Stellen gepflegt werden muss (Konstruktor und Init-Funktion), sowas geht in der Regel nicht lange gut. Besser wäre, im Konstruktor Init aufzurufen. Richtiges C++ wäre, die Konten nicht in einem C-Style-Array zu verwalten, sondern in einem STL-Container, z.B. std::vector<Konto> oder std::list<Konto>. Dann könnte man nämlich parameter-konstruierte Konto-Objekte in den Container stecken, der dynamisch wachsen würde, und bräuchte die Init-Geschichte gar nicht.
Zitat: |
Etwas eigenartig finde ich auch die Funktion suchen(), die keine Parameter hat.
|
Die sollte allerdings besser "get_kontonummer ()" oder so heißen.
Zitat: |
Kommen wir zur main()-Funktion ... Da wird doch tatsächlich diese doofe init-Funktion benutzt ... gibt es da doch bestimmt auch bessere Lösungen.
|
Jawoll, siehe oben.
Zitat: |
Als nächstes: Was soll diese Sprungmarke Menue: vor der while-schleife? -
|
Altlast aus früheren Jahrhunderten. Wird nirgendwo mehr verwendet und trägt nur zur Verwirrung bei. Sollte gelöscht werden.
Zitat: |
Danach die Auswahl, wobei ich mich frage, warum die Variable auswahl global definiert ist, obwohl sie nur in main benötigt wird. Dann ist ihr Wert beim Programmstart unbestimmt, sie wird aber bereits in der Abbruchbedingung der Schleife verwendet. Das kann doch nicht gut gehen! => Logischer Fehler.
|
NACK. Globale Variablen werden mit 0 initialisiert, kein Fehler. Aber es stimmt, die Variable könnte genausogut lokal sein, bräuchte dann aber eine Initialisierung.
Zitat: |
Was soll das getch() jedesmal am Ende eines case-Blocks?
|
Das Programm anhalten, damit der Benutzer die letzte Ausgabe sehen kann. Wenns schee macht ...
Zitat: |
Weiter fällt mit die Funktion Konto::ausgabe() auf, in der printf benutzt wird. Aber formatierte Ausgaben kann man doch auch mit cout bewerkstelligen. Ich weis zwar (noch) nicht genau, wie ...
|
Der Autor offenbar auch nicht. Aber es stimmt, man sollte entweder printf oder cout nehmen, aber nicht beides. Die Mischung kann - muss aber nicht - zu lustigem Durcheinander auf dem Bildschirm führen.
Zitat: |
Zusammenfassend würde ich sagen, das dieses Programm eine Katastrophe ist, weil es viel zu viele Fehler enthält ...
|
Zu den gröbsten Fehlern gehört IMHO der selbstgebastelte Typ string, der ohne jedes Range-Checking blind verwendet wird. Namen über 30 Zeichen sind zwar in unseren Breiten selten, aber wenn beim ersten pakistanischen Kunden, der ein Konto eröffnen will, gleich die EDV abstürzt, ist das nicht so witzig.
Dazu kommt dieses C-C++-Mischmasch (Datenhaltung im C-Style-Array, wo ein STL-Container viel passender wäre), das einem viele nützliche Hilfen verbaut, z.B. Suchen auf dem Container, und einen zwingt, den ganzen Mist selber zu machen.
Und dann sind da noch etliche Nachlässigkeiten, die zwar nicht gleich zu Fehlern führen, aber den Code missverständlich und unsauber machen.
Wirklich kein Vorführstück.
ao Dieser Post wurde am 15.03.2006 um 09:17 Uhr von ao editiert. |