PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Makefile und undefined reference



dipesh
10-10-2004, 18:09
Hallo liebe Entwickler,

aus dem Bedürfnis heraus mich nähr mit C++ zu beschäftigen, hab ich angefangen einige kleinere Projekte umzusetzen. Bei einem dieser Projekte stehe ich vor dem Problem, nicht sonderlich viel von Makefiles zu verstehen und eine für mich obskure Fehlermeldung zu erhalten. Die letzten Stunden try-and-error und durchsuchen diverser Makefile-Howtos half leider nicht weiter und so hoffe ich jemand hier im Forum könnte mir eine Anregung geben.

Zum Sachverhalt (die Quellen wurden aufs wesentliche reduziert);

main.cpp


#include "config.h"
#include <string>
int main(int argc, char **argv){
testcase::Config::WorkPath = "/home/dipesh/testcase/";
return 0;
}

config.h


#include <string>
namespace testcase {
class Config {
public:
static std::string WorkPath;
};
//std::string Config::WorkPath = "/home/dipesh/anothertestcase/";
}

Makefile


CC = g++ -g -Wall
BIN = mytestcase
CFLAGS =
LDFLAGS =
all: main.o
<tab>$(CC) main.o -o $(BIN) $(LDFLAGS)
main.o: main.cpp config.h Makefile

Beim Versuch das Ganze mittels make zu kompilieren erhalte ich eine Fehlermeldung der Art


In function `main':
: undefined reference to `testcase::Config::WorkPath'


In den qmake pro-Dateien gibt es die nette Variante SOURCES und HEADERS zu definieren und gut ist. Nur wie wird das bei Makefiles definiert? Ein einfaches #include "config.h" in der main.cpp scheint wohl nicht ausreichend zu sein. Zumal die config.h später ebenfalls in anderen cpp-Dateien zum Einsatz kommen soll und die definierten statischen Variablen auf diesem Wege allen Klassen zur Verfügung stehen sollen.
Danke im voraus für jeden Hinweis bzw. jede Anregung.

dipesh
10-10-2004, 19:19
Mir ist zwar nicht bewusst warum, aber wenn ich eine config.cpp mit aufnehme und statt in der .h dort
std::string Config::WorkPath = "/home/dipesh/anothertestcase/";
eintrage, funktioniert das Ganze wie gewünscht...
Scheint wohl, daß eine .h-Datei alleine nicht in der gewünschten Weise verarbeitet werden kann. Interessant.

locus vivendi
11-10-2004, 08:39
Scheint wohl, daß eine .h-Datei alleine nicht in der gewünschten Weise verarbeitet werden kann.
Das schon. Die Deklaration einer statischen Variable in einer Klasse ist allerdings keine Definition. Eine Definition ist das was du in deine config.cpp eingetragen hast. Wäre die Deklaration einer statischen Variable in einer Klasse auch eine Definition, würde das ja zu Fehlern führen wenn die Header Datei mehrmals inkludiert wird. Dann hätte man mehrere Definitionen ein und derselben Sache in einem Programm, und das ist (natürlich) verboten.

dipesh
14-10-2004, 13:23
Die Deklaration einer statischen Variable in einer Klasse ist allerdings keine Definition. Eine Definition ist das was du in deine config.cpp eingetragen hast.
Davon ging ich auch aus. Daher auch der Versuch der Definition mit der auskommentierten Zeile in config.h.


Wäre die Deklaration einer statischen Variable in einer Klasse auch eine Definition, würde das ja zu Fehlern führen wenn die Header Datei mehrmals inkludiert wird.
Die mehrfache Inkludierung wird doch durch die Angabe von
#ifndef _myproject_myfile_h
#define _myproject_myfile_h
...
#endif
innerhalb der Headerdatei verhindert. Das define sollte doch eigentlich Projektweit für alle h/cpp-Dateien gelten und die Headerdatei somit im gesamten Projekt genau 1x (vorausgesetzt sie wird überhaupt irgendwo inkludiert) gleichsam als forward-Deklaration eingebunden werden.
Memberfunktion können in einer Headerdatei schließlich auch gleichzeitig deklariert und definiert werden ( class MyClass { void tunichts(){} } ; ), warum geht dies also nicht mit (statischen) Membervariablen?

locus vivendi
14-10-2004, 15:12
[...] Das define sollte doch eigentlich Projektweit für alle h/cpp-Dateien gelten und die Headerdatei somit im gesamten Projekt genau 1x (vorausgesetzt sie wird überhaupt irgendwo inkludiert) gleichsam als forward-Deklaration eingebunden werden.
Das gilt nur für eine Übersetzungseinheit. Wird ein Programm aus mehreren Übersetzungseinheiten zusammengelinkt, würden mehrfache Definitionen entstehen.



Memberfunktion können in einer Headerdatei schließlich auch gleichzeitig deklariert und definiert werden ( class MyClass { void tunichts(){} } ; ), warum geht dies also nicht mit (statischen) Membervariablen?
Weil man es so festgelegt hat. Inline - Funktionen und Templates dürfen mehrfach definiert werden. Für diese Konstrukte ist es ja auch notwendig das ihre Definition in jeder Übersetzungseinheit in der sie benutzt werden sichtbar ist.

dipesh
19-10-2004, 18:38
Danke :-)
(zehn Zeichen +n)