Static Memberfunktionen
- 
					
					
					
					
 Tag, ich habe da ein Problem wo ich nicht weiter komme. Ich habe laut sämtlichen mir zur Verfügung stehenden Büchern und Google alles richtig gemacht. Es geht darum, dass ich eine Klasse habe, die ausschliesslich static Variablen und Methoden besitzt (Ich weiß, kein guter Stil, aber es geht hier ums Prinzip  ) )Wenn ich, wie es sein sollte, alles (Var. und Meth.) static deklariere, um in der main() z.B. mit foo::Methode() auf eine Methode zuzugreifen, dann schmeisst er mir jede Menge Fehlermeldungen an den Kopf: hauptklasse_Init.obj : error LNK2001: unresolved external symbol "public: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl hauptklasse::IntegerToString(int)" (?IntegerToString@hauptklasse@@SA?AV? $basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z) hauptklasse_Init.obj : error LNK2001: unresolved external symbol "public: static void __cdecl hauptklasse::putAblauf(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?putAblauf@hauptklasse@@SAXV?$basic_strin g@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) planet_GetCp.obj : error LNK2001: unresolved external symbol "public: static void __cdecl hauptklasse::putAblauf(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?putAblauf@hauptklasse@@SAXV?$basic_string@DU ?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) planet_GetCp.obj : error LNK2001: unresolved external symbol "public: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl hauptklasse::GetData(char const *)" (?GetData@hauptklasse@@SA?AV?$basic_stri ng@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PBD@Z) planet_leseVerteidigung.obj : error LNK2001: unresolved external symbol "public: int __thiscall hauptklasse::StringToInt(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?StringToInt@hauptklasse@@QAEHV?$basi c_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) planet_leseFlotten.obj : error LNK2001: unresolved external symbol "public: int __thiscall hauptklasse::StringToInt(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?StringToInt@hauptklasse@@QAEHV?$basic_str ing@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) planet_leseForschung.obj : error LNK2001: unresolved external symbol "public: int __thiscall hauptklasse::StringToInt(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?StringToInt@hauptklasse@@QAEHV?$basic_s tring@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) planet_leseGebaeude.obj : error LNK2001: unresolved external symbol "public: int __thiscall hauptklasse::StringToInt(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?StringToInt@hauptklasse@@QAEHV?$basic_st ring@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) planet_leseUebersicht.obj : error LNK2001: unresolved external symbol "public: int __thiscall hauptklasse::StringToInt(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?StringToInt@hauptklasse@@QAEHV?$basic_ string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) planet_leseVerteidigung.obj : error LNK2001: unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall hauptklasse::FindeDenWertZwischen(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?FindeDenWertZw ischen@hauptklasse@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V23@0AAV23@@Z) planet_leseFlotten.obj : error LNK2001: unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall hauptklasse::FindeDenWertZwischen(class std::basic_string<char,struct std: :char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?FindeDenWertZwische n@hauptklasse@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V23@0AAV23@@Z) planet_leseForschung.obj : error LNK2001: unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall hauptklasse::FindeDenWertZwischen(class std::basic_string<char,struct st d::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?FindeDenWertZwisc hen@hauptklasse@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V23@0AAV23@@Z) planet_leseGebaeude.obj : error LNK2001: unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall hauptklasse::FindeDenWertZwischen(class std::basic_string<char,struct std ::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?FindeDenWertZwisch en@hauptklasse@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V23@0AAV23@@Z) planet_leseUebersicht.obj : error LNK2001: unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall hauptklasse::FindeDenWertZwischen(class std::basic_string<char,struct s td::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?FindeDenWertZwis chen@hauptklasse@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V23@0AAV23@@Z) planet_leseUebersicht.obj : error LNK2001: unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall hauptklasse::FindeDenWertZwischen(class std::basic_string<char,struct s td::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,char)" (?FindeDenWer tZwischen@hauptklasse@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V23@0AAV23@D@Z) Main.obj : error LNK2001: unresolved external symbol "public: static void __cdecl hauptklasse::PaintMenue(void)" (?PaintMenue@hauptklasse@@SAXXZ) Debug/OgameAllroundTool.exe : fatal error LNK1120: 7 unresolved externals Error executing link.exe.So. Deklariere ich aber ausschliesslich die Variablen als Static, und die Methoden normal, also so, dass ich in der main() erstmal mit "foo objekt" ein Objekt der Klasse anlegen muss, und dann per objekt.MethodeVonFoo() auf die Methoden zugreifen, dann funktioniert es einwandfrei, keine Fehler. Hier mal die Klasse: class hauptklasse { public: static string jede, Menge, Variablen, static void PaintMenue(); static void MainConfigReader(); static BOOL WriteClipboardData(LPCTSTR lpszInputText); static void putAblauf(string data); // Und ne Menge anderer Methoden };Und dann noch ein kleines Beispiel aus einer der Quelltextdateien, die einen Linking Error verursachen: #include "derived.h" //Diese Klasse hat von "hauptklasse" geerbt. void derived::LeseDaten() { variableAusHauptklasse = StringToInt(FindeDenWertZwischen("Benutzername=", " ;)", flotte)); //Also: StringToInt kommt aus der Hauptklasse, ebenso wie FindeDenWertZwischen. //und ein paar andere Variablen aus Hauptklasse die einen Wert zugewiesen bekommen }Mehr Angaben fallen mir nicht ein, die ich machen könnte. 
 Und bitte nicht meinen Stil kritisieren, mir ist klar, man kann das alles auch viel eleganter lösen, aber wie gesagt es geht ums Prinzip Danke! 
 
- 
					
					
					
					
 Würde mal annehmen es fehlen die implementationen (vielleicht sollte es initialisierung heissen ) deiner statischen Variablen. 
 Irgendwo im hauptklasse.cpp fehlt:string hauptklasse::jede = "jede"; string hauptklasse::Menge = "Menge";.... Kurt 
 
- 
					
					
					
					
 Ich hab es gerade einmal mit initialisierung der Variablen versucht, aber die Fehlermeldung ist die gleiche.  
 
- 
					
					
					
					
 Ich kann Deine Fehlermeldung hier nicht nachvollziehen: haeader: class hauptklasse { public: static int iNo; static std::string szText; static void SetNo (int iNoToset); static void PaintMenue(); };Body: #include <stdio.h> #include <string> #include <iostream> #include "hauptklasse.h" int hauptklasse::iNo = 1; std::string hauptklasse::szText = "ABCDE\n"; void hauptklasse::SetNo (int iNoToset) { iNo = iNoToset; } void hauptklasse::PaintMenue (void) { printf ("Test\n"); }Main: #include <stdio.h> #include <string> #include <iostream> #include "hauptklasse.h" int main (int argc, char **argv) { hauptklasse::SetNo (4711); printf ("%d\n", hauptklasse::iNo); std::cout << hauptklasse::szText; hauptklasse::PaintMenue (); }compiliert ohne Warnung und erzeugt: 4711 
 ABCDE
 TestAls Output 
 
- 
					
					
					
					
 Was passiert denn, wenn du es jetzt z.B. so machst: Body: #include <stdio.h> #include <string> #include <iostream> #include "hauptklasse.h" int hauptklasse::iNo = 1; std::string hauptklasse::szText = "ABCDE\n"; void hauptklasse::SetNo (int iNoToset) { iNo = iNoToset; } void hauptklasse::PaintMenue (void) { printf ("Test\n"); SetNo(2); //Gibt es hier ein unresolved Symbol? }main: #include <stdio.h> #include <string> #include <iostream> #include "hauptklasse.h" int main (int argc, char **argv) { hauptklasse::PaintMenue (); printf ("%d\n", hauptklasse::iNo); return 0; }
 
- 
					
					
					
					
 Nee. 
 
- 
					
					
					
					
 Ähh... Ne? Wie jetzt? 
 
- 
					
					
					
					
 PeterP schrieb: Ähh... Ne? Wie jetzt? Kein unresolved symbol. Warum auch ? 
 Kurt
 
- 
					
					
					
					
 Offengestanden, ich habe eher den Verdacht, dass der Linker nichts von hauptmenue-Objectdatei weiss. Ich weiss nicht welchen Compiler und Linker Du benutzt, aber schau mal in diese Richtung. 
 
- 
					
					
					
					
 Mhhh ist schon merkwürdig. Ich verwende Microsoft Visual C++ 6.0. 
 Ich hab absolut keine Ahnung wo ich noch nach dem Fehler suchen soll. Die Sources, so wie ihr sie hier gepostet habt, laufen ja auch (btw, vielen Dank für die Mühe).Nur bei mir im Programm muss etwas anders laufen, als dort. Nur was? Das ist ein großes Projekt, d.h. auch ziemlich schwer den Fehler zu finden 
 
- 
					
					
					
					
 Wennd as Projekt wirklich groß ist, solltest du daran denken, Unittests durchzuführen. Sprich: schreib für jede komplexere Klasse und für jede kleinere Gruppe zusammengehörender Klassen Kleine Programme, die nichts anderes tun als die KLassen auf ihre Funktionalität zu überprüfen. 
 Sprich:
 - für jede Methode, die eine Klasse anbietet, solltest du eine Handvoll repräsentativer Aufrufe machen und die Ergebnisse überprüfen.
 - Mache außerdem Aufrufe für den Grenzbereich der akzeptierten Werte, zum Beispiel bei Numerischen Argumenten den größtmöglichen Wert usw.
 - gehe nicht von Annahmen aus, was das Verhalten einzelner Codestücke angeht, sondern beweise für dich selbst schriftlich, dass dein Code sich so verhält, wie erwartet. Das bedeutet nicht, dass du deine function(int) einmal mit 5 aufrufst udn bemerkst, dass dass richtige Ergebnis rauskommt, sondern dass du für jeden Annehmbaren Wert zeigstm dass die Funktion das richitge Ergebnis liefert. Das bedeutet, auf dinge wie (beispielsweise) mögliche Division durch 0 im Code zu achten etc.
 - schreibe an deine Methoden im Quellcode Kommentare, für welchen Wertebereich sie richtige Ergebnisse liefern soll, und überprüfe, ob du sie auch nur in dem Wertebereich benutzt. Beispielsweise muss für die Funktion "div(float x, float y)" vor Aufruf feststehen, dass y nicht 0 ist. Das ist nicht Aufgabe der Funktion, das zu prüfen, sondern des Aufrufers. Sowas kann man beispielsweise so formulieren:float div(float x, float y) /** Contidions: * @pre: y != 0 * @post: div(x,y) * y - x <= std::numeric_limits<float>::epsilon */ { //... }Ansonsten: prüfe deinen Code sorgfältig auf Dinge wie default Ctor und Copy-Ctor, default operator=, default Dtor, new&delete bzw. new[]&delete[], diverse Arten von Memoryleaks (z.B. virtuelle Dtors bei Basisklassen) etc. Und schleßlich und endlich: Kommentiere deinen Quellcode ausführlich, alles was du zusichern kannst und nicht zusichern kannst, alles was getestet und nicht getestet wurde etc. 
 
- 
					
					
					
					
 Ok, vielen Dank für die Tipps, ich werd das mal überarbeiten, vielleicht wirds dann ja was. 