PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Methoden/Klassen [C/C++]



Dingsi
25.06.2006, 12:29
Zwei Sachen: Gib die genaue Fehlermeldung, mit Zeilenangaben und allem drum und dran. Nur "Da fehlt angeblich irgendwo irgendwas" bringt's nicht so. Beim Überfliegen ist mir erstmal nichts konkret aufgefallen.

Zweitens: Liegt das am Forum, oder hast du einen grausigen Codestil? Im ersten Moment dachte ich wegen der merkwürdigen Einrückung, dass du main() in class kkk* definiert hast. Außerdem kann ich Horstmann (http://de.wikipedia.org/wiki/Einr%C3%BCckungsstil#Variation:_Horstmann) nicht ab. :B

*kkk ist übrigens ein sehr schlechter Name für eine Klasse, mMn. Die Namen sollten aussagekräftig sein, damit ein anderer Mensch als du den Code auch verstehen kann und auch damit du ihn selbst, in ein paar Wochen oder Monaten noch verstehst.

Okay, das waren jetzt drei Sachen. ôô

Dingsi
25.06.2006, 13:04
Fehler E2233 6: Klassenelement kann hier nicht initialisiert werden Probier doch erstmal den Fehler zu berichtigen... Ist das die Zeile mit protected : static int ktn=21547615;?

Zu der Sache mit der PIN: Nope, keine Ahnung, Sorry. Mit Passworteingabe auf dem Terminal hatte ich noch nicht zu tun.

DFYX
25.06.2006, 15:01
Wär praktisch, wenn du uns mal sagen könntest, welches die Zeile 67 ist. Ich hab momentan ehrlich gesagt keine Lust, das von Hand abzuzählen und Nummerierungen in [code] Block haben wir ja leider keine (Memo an mich selbst: Admins anquatschen)

Lysandros
25.06.2006, 15:58
Hi, also ich hab es mal bei mir compiliert und folgende Fehler erhalten:


E:\Temp\c++\help.cpp:68: error: request for member `num' in `k3', which is of non-class type `kkk ()()'
E:\Temp\c++\help.cpp:70: error: request for member `ein' in `k1', which is of non-class type `spk ()()'
E:\Temp\c++\help.cpp:71: error: request for member `ist' in `k1', which is of non-class type `spk ()()'

E:\Temp\c++\help.cpp:75: error: request for member `auszug' in `k1', which is of non-class type `spk ()()'
E:\Temp\c++\help.cpp:77: error: request for member `zinse' in `k1', which is of non-class type `spk ()()'
E:\Temp\c++\help.cpp:79: error: request for member `auszug' in `k1', which is of non-class type `spk ()()'
E:\Temp\c++\help.cpp:81: error: request for member `zinse' in `k3', which is of non-class type `kkk ()()'
E:\Temp\c++\help.cpp:83: error: request for member `auszug' in `k3', which is of non-class type `kkk ()()'

ich glaube damit kannst du mehr anfangen als mit den Fehlermeldungen, die du erhalten hast. (btw einfach eine Zeile abziehen, damit du dieselbe hast) Ich kenn mich aber zu wenig mit C++ aus, um Lösungen anzubieten...

MuadDib
26.06.2006, 09:43
Okay.... wo fangen wir an. Am besten beim Stil: Gewöhn dir eine andere, lesbarere Klammernsetzung an und verwende nebenbei vielleicht eine andere Art und Weise, wie du Variablen, Klassen und Methoden benamst: Im Grunde ist bei dir ja alles klein geschrieben, Klassen groß, Methoden in CamelCase, und Variablen klein... so wird das ganze viel lesbarer. Sieh dir diesen Link (http://geosoft.no/development/javastyle.html) - als kleinen Denkanstoß.

Gehen wir dann weiter zu Problem No. 1 -> Die Kontonummer
Im Grunde deklarierst du ein statisches Feld und setzt es bei jedem Konstruktoraufruf wieder auf einen Wert zurück. Sprich, es hat auch nach dem x-ten Objekt, dass du erzeugst, den gleichen Wert. Weiteres Problem: Wenn du mit num() versuchst, die Kontonummer zu erhöhen, haben - aufgrund des statischen Felds - auch alle Objekte wiederum die gleiche Kontonummer, und ich denke einmal, dass ist nicht erwünscht. Versuch stattdessen folgende Variante:



#include <iostream>
#include <stdio.h>
#include <string.h>

// namespace verwenden!
using namespace std;

int ktn = 2000;

class spk
{

protected :

int myktn;
char inh[20];
double stand;
double zins;

...
};


myktn wird der Platzhalter für jedes Objet, der die Kontonummer trägt, ktn als globale Variable ist der Zähler, der die aktuelle, freie Kontonummer trägt. Verwende btw. einen long, ich weiß nicht, wie groß Kontonummern werden können. MitKonstruktoraufruf sollte es dann so aussehen:



class spk
{

protected :

int myktn;
char inh[20];
double stand;
double zins;

void setFields(const char* name, double s, double z) {
strcpy(inh, name); //String-Copy Falsch gewesen!
stand=s;
zins=z;
}

public :
spk()
{
setFields("Unbekannt", 0.0, 0.02);
myktn = ::ktn++;
}

spk(const char* name, double s, double z)
{
setFields(name, s, z);
myktn = ::ktn++; // Static fields richtig nützen!!
}

...
}


Ich weiß, es geht noch schöner, aber dafür hab ich keine Zeit. ktn wird dabei jedes Mal um eines erhöht, wenn du ein Objekt anlegst... myktn bleibt read-only und wird nicht verändert, und trägt die Nummer zur Erzeugung des Objektes.

Natürlich musst du dann deine Auszug auch ändern:



void auszug (void)
{
cout<<"Kontonummer "<< myktn << endl;
cout<<"Kontoinhaber "<< inh << endl;
cout<<"Kontostand "<< stand << endl << endl;
}

Schöner ist es übrigens, wenn du dir da einen String erzeugen lässt, anstatt cout zu verwenden, aber das ist eine andere Geschichte. num löschen wir, und zinse ändern wir auch etwas ab:


// Wann wird verzinst?
virtual void zinse (void)
{
stand=stand+stand*zins;
}


Warum? Nun... im Grunde willst du bei der Klasse kkk ja nur eine andere Verzinsung anwenden. Du hast allerdings eine weitere Methode dazu geschrieben, auch wenn sich nur eine Variable ändert. Mit virtual deklarieren (um auch ein spk *x= new kkk() erzeugen zu können) und überschreiben ist viel schöner! Du hast bei der Vererbung zwar richtig public abgeleitet, aber nicht mit Superkonstruktoren gearbeitet. Ausserdem hast du bei der Deklaration in der main-Methode auch ein paar Fehler drin, die deine Klassen nicht als Obhejte, sondern als structs erkannt haben, warum auch immer. Die neue, hübschere Klasse sieht so aus:



class kkk: public spk
{

public :

//besser: zinse in spk virtual deklarieren!
void zinse()
{
zins = (stand > 0) ? 0.005 : 0.01;
spk::zinse();
}

kkk() : spk() { }

kkk(const char* name, double s, double z) : spk(name, s, z) { }
};


Wo genau die Fehler waren, weiß ich nicht mehr... ich hab einfach deinen Code hergenommen und ihn ausgebessert, um ein schöneres Bild zu bekommen... und danach hats funktioniert - einer der Schlauen wird dir sicher die Fehler erklären können, wenn er unsere Quelltexte vergleicht, ich hab keine Zeit dazu.

Der Schluß sieht auf jeden Fall so aus:

int main()
{
spk k1;
spk k2("Heinzelmann", 2500.0 , 2.0);
kkk k3;
kkk k4("Mustermann", 1000.0,0.0);

k1.ein(500.0);

cout<<"Kontostand KTO 1: " << k1.ist() << endl;
cout<<"Kontostand KTO 2: " << k2.ist() <<endl;

k1.auszug();
k2.auszug();
k1.zinse();
k2.zinse();
k1.auszug();
k2.auszug();
k3.zinse();
k4.zinse();
k3.auszug();
k4.auszug();

return 0;
}

Und funktioniert auch.

Der gesamte Code (inklusive ein paar Überbleibsel deiner Fehler, grausamer Formatierung durch copy & paste und ein paar Kommentaren, die du dir hinter die Ohren schreiben solltest) ist noch einmal angehängt.

MuadDib
27.06.2006, 09:25
Das mit der Kontonummer war neu für mich, da ich static noch nie benutz habe, nur aus nem Tutorial genommen und gepastet habe...ohne zu überlegen...Asche auf mein Haupt.
Wirklich... sowas macht man nicht - Fremde Codezeilen in allen Ehren, aber wenn man nicht versteht, was dahinter passiert, soll mans lassen :P ;)



Das mit der Formatierung ist der grausame Compiler in unserer Schule, tut mir leid.
Nicht der Compiler, wenn dann der Editor



Warum strcpy falsch war, weis ich nicht, bei mir hats gefunzt.
Es hat kompiliert, das heisst aber unter C/C++ noch lange nicht, dass es funktioniert. Du hast die Parameter vertauscht und den leeren (bzw. mit Datenmüll vollen) String inh in den übergebenen String name kopiert, ich schätze, du wolltest das umgekehrte...



Was bitte ist ein Superkonstruktor, sowas zum Essen?! :D

Ein Aufruf des Konstruktors der Oberklasse... erspart dir viel Tipparbeit


EDIT: Achso, ich vergaß, ich wollte ja noch beim initialisieren einen vierstelligen PIN abfragen, wobei natürlich die Eingabe als Sterne zusehen sein soll...Hättest du, oder jemand anderst noch ne Idee dazu?
Hm... ist noch ungetestet (hab leider keine conio....), aber versuch einmal das:


#include <stdio.h>
#include <conio.h>

int main(int argc, const char **argv) {
char ch;
char pass[4];
int i = 0;

while(i < 4) {
pass[i++] = getch();
putch('\010');
putch('*');
}
putch('\n');

return 0;
}