Definition von static member Funktion in .cpp file
-
Hallo,
ich bin neu bei C++ (vorher C) und habe folgendes Problem, welches ich mir nicht erklären kann. Und zwar möchte ich mir eine Klasse bauen, um mit Exceptions umzugehen (ob die nun in der Form sinnvoll ist oder nicht, sei mal dahingestellt).
Wie auch immer, die Klasse macht mir beim Kompilieren Probleme, genauer gesagt die static member Funktionen der Klasse. Die Definition der Klasse ist im .hpp File, die Definition der Funktionen im .cpp File, also genauer:
class Exception{ public: Exception(){} inline static void error_exit (char *error_message); inline static void error_test (void *pointer, char *error_message); void test (); //private: };(Eigentlich soll die Klasse nur static Funktionen haben mit private Konstruktor, es ist nur gerade so wegen der Testfunktion.)
Im .cpp File habe ich nun die Funktionen definiert, also
using namespace std; inline void Exception:: error_exit (char *error_message){ cerr << "ERROR: " << error_message << std::endl; exit(EXIT_FAILURE); return; } inline void Exception:: error_test (void *pointer, char *error_message){ if (pointer == NULL){ cerr << "ERROR: " << error_message << endl; exit(EXIT_FAILURE); } return; } void Exception:: test(){ return; }Nun folgender Aufruf:
Exception ex; ex.test(); Exception:: error_exit("blubb");Der erste Aufruf ex.text() funktioniert, aber beim Aufruf der static Funktion sagt mir der Compiler:
undefined reference to Exception::error_exit(char*)
und ich verstehe nicht, wieso.
Packe ich die Funktionsdefinitionen in die Header-Datei (was ich allerdings nicht möchte), funktioniert es auch.
Was ist falsch?
Ich entschuldige mich für die etwas langen Beispiele, aber ich wollte es genauso einbauen, wie es ist gerade im Code ist.
Vielen Dank schonmal im Voraus,
plizzz
-
Mach mal das inline raus, bringt dir eh nichts. (Und das da ist schlechtes C mit Klassen, was genau willst du damit erreichen? oO)
-
Ok, hat tatsächlich an inline gelegen, danke für den schnellen Tipp. Warum funktioniert inline da nicht und warum bringt es nichts?
Und zum zweiten Kommentar: Ich habe etwas C programmiert und dort meine Exceptions mit solchen Funktionen behandelt. Vielleicht kann man besser mit Exceptions umgehen, aber ich wollte mich jetzt beim Umstieg auf C++ erstmal auf andere Dinge konzentrieren. Aber ja, die Klasse Exceptions ist nicht nötig, ich hätte auch einfach void Funktionen ohne Klasse definieren können. Aber warum ist das schlechtes C?
(Ich habe übrigens schon die Parameter auf const char* geändert, bevor dieser Tipp kommt.)
MfG plizz
-
plizzz schrieb:
Ok, hat tatsächlich an inline gelegen, danke für den schnellen Tipp. Warum funktioniert inline da nicht und warum bringt es nichts?
inline hat zwei Funktionen, die erste ist sinnvoll, die zweite nicht (mehr).
Die erste bewirkt, dass eine Funktion mehrmals definiert sein darf. Dadurch kannst du auch freie Funktionen im Header definieren. (Was sonst nicht gehen würde, da dieser ja öfter eingebunden werden könnte.) (Templates sind übrigens automatisch inline.)
Die zweite Funktion (die du wahrscheinlich erreichen möchtest) ist ein Tipp an den Compiler, dass er diese Funktion doch bitte inlinen soll. Das hat bei modernen Compilern aber kaum einen Effekt, da diese eh besser als du wissen was man inlinen sollte und was nicht.plizzz schrieb:
(Ich habe übrigens schon die Parameter auf const char* geändert, bevor dieser Tipp kommt.)
Na immerhin, das war der größte Patzer. Aber warum schreibst du return; ans Ende einer void Funktion? Insgesamt scheint mir das Konzept etwas eigenartig zu sein.
Um aber zum C++ Teil zu kommen: Diese Klasse macht keinen Sinn. Klassen sind dann sinnvoll, wenn die Objekte der Klasse irgendwelche Eigenschaften haben über die sie sich definieren. Hier wären dagegen eher freie Funktionen (eventuell in einem Namespace) angebracht. Weiter gibt es in C++ auch echte Exceptions, warum nutzt du die nicht einfach? Wenn du dich nicht lange damit beschäftigen möchtest, wirf halt std::runtime_error. Aber versuche nicht zwanghaft ein C Konzept in eine Klasse zu stopfen, dadurch wird es kein (schönes) C++.
-
templates sind übrigens nicht automatisch inline.
es gibt ne ausnahme in der ODR für templates
aber inline sindse deswegen nicht

-
Naja, ob ich jetzt freie Funktionen in einen eigenen Namespace schreibe oder eine Klasse benutze, ist doch letztlich abgesehen von einer Stilfrage egal, oder nicht? Genauso tut es doch keinem Weh, ob ich nun return; ans Ende einer void-Funktion schreibe oder nicht.
Edit: Ich verstehe immernoch nicht, warum ich diese Funktionen nicht inline definieren darf (unabhängig davon, ob es nun was bringt oder nicht)?
-
Du darfst Funktionen inline deklarieren soviel du willst, benutzen darfst du sie aber nur in Übersetzungseinheiten, in denen diese inline-Funktionen auch definiert werden.
-
plizzz schrieb:
Naja, ob ich jetzt freie Funktionen in einen eigenen Namespace schreibe oder eine Klasse benutze, ist doch letztlich abgesehen von einer Stilfrage egal, oder nicht?
Von Klassen kann man Objekte instanziieren, von namespaces nicht. Wenn das Interface nur aus static-Funktionen bestehen soll, machen Instanzen keinen Sinn, oder? Von daher -> nimm namespace!
(Du könntest Konstruktor private machen, um das Instanziieren zu unterdrücken, aber mal ehrlich...)
-
plizzz schrieb:
Naja, ob ich jetzt freie Funktionen in einen eigenen Namespace schreibe oder eine Klasse benutze, ist doch letztlich abgesehen von einer Stilfrage egal, oder nicht?
Ja, es ist eine Stilfrage. const-correcteness ist irgendwo auch eine Stilfrage. Objektorientierung und Softwarearchitektur auch. Funktionieren tut vieles, aber das heißt nicht, dass es keinen bevorzugten Weg gibt.
plizzz schrieb:
Genauso tut es doch keinem Weh, ob ich nun return; ans Ende einer void-Funktion schreibe oder nicht.
"return;" impliziert (für mich?) den Abbruch einer Schleife oder das Überspringen der restlichen Anweisungen, daher finde ich es komisch.
-
Wenn ich das nun richtig verstanden habe, ist es so, dass ich Inline-Funktionen nur in dem .cpp-File verwenden kann, in dem sie definiert wurden, was wohl daran liegt, dass der Compiler bei der Verwendung einer inline-Funktion tatsächlich deren Quelltext kennen muss (?). Wie umgeht man dieses Problem am elegantesten? Definiert man global gebrauchte Inline-Funktionen einfach in Header-Dateien?
-
lass das inline einfach weg. wenn du dir sorgen um die geshcwindigkeit machst, dann schreib erstmal ein funktionierendes programm und optimiere es dann, zum beispiel mit einem profiler.
aber dir hier syntax fehler einzubauen, für was was eh nicht geht oder dir nichts bringt, das ist schwachsinn
-
plizzz schrieb:
Wenn ich das nun richtig verstanden habe, ist es so, dass ich Inline-Funktionen nur in dem .cpp-File verwenden kann, in dem sie definiert wurden, was wohl daran liegt, dass der Compiler bei der Verwendung einer inline-Funktion tatsächlich deren Quelltext kennen muss (?).
richtig.
Wie umgeht man dieses Problem am elegantesten?
Einfach nicht als inline deklarieren.
Definiert man global gebrauchte Inline-Funktionen einfach in Header-Dateien?
Andersrum: Wenn du eine Funktion unbedingt in einem Header definieren willst, dann inline.
Nochmal: Inline hat zwei Funktionen:
-
"ODR-Schutz": Eine inline deklarierte Funktion darf in mehreren Übersetzungseinheiten definiert sein, die Definitionen müssen "gleichwertig" sein. Am Einfachsten erreicht man das, indem man sie gleich in den Header schreibt, der die Funktion deklariert.
Eine inline deklarierte Funktion muss in allen ÜEs definiert sein, die sie benutzen, was hier die Fehlerursache ist. -
Inline-Hinweis für den Compiler: Der Compiler darf den Code der Funktion an Stelle der Funktionsaufrufe schreiben - was der Grund ist, warum er in den ÜEs, in denen die Funktion aufgerufen wird, auch den Code, d.h. die Definition, kennen muss. Der Compiler muss den Code aber nicht inlinen, darf aber andererseits inlinen, auch wenn die Funktion nicht inline deklariert ist (geht zur Compilezeit natürlich nur innerhalb der ÜE, wo die Funktion definiert ist). Das ganze Inlining sollte man in erster Näherung erstmal dem Compiler (und/oder Linker) überlassen.
Fazit: Definiere deine Funktionen in der .cpp, ohne die an der Stelle sinnfreie inline-Deklaration.
-
-
Okay, danke.