multiple definition - oder: was läuft schief beim includieren?
-
hi
Beim Kompilieren meines Projekts bekomme ich folgende Fehlermeldung (DEV-C++ Version 4.9.8.0):
vertex.cpp d:\nws\MaturArbeit\ProgramCode\DosApp\vertex.o(.text+0x3e) __multiple definition of `CEdge::CEdge(int, int, double)' dijkstra.cpp d:\nws\MaturArbeit\ProgramCode\DosApp\dijkstra.o(.data+0x0) __multiple definition of `CVertex::TotalVNr' dijkstra.cpp d:\nws\MaturArbeit\ProgramCode\DosApp\dijkstra.o(.text+0xaa0) __multiple definition of `CDijkstra::DijkstraSolve()' ...usw...
ich bin mir sicher, dass ich keine Datei doppelt includiert habe.
die "IncludierStruktur" sieht folgendermassen aus: ("->" = "wird includiert von")Edge.cpp -> Vertex.cpp -> Graph.cpp -> Dijkstra.cpp -> ReadFromTxt.cpp -> Main.cpp
Jedes .cpp includiert auch noch das zugehörige .hHier das Projekt (HTML): http://www.nrg.to/ultinate/PathFinder_v0.2.htm
(ZIP): http://www.nrg.to/ultinate/DosApp.zipBin sehr froh um eure Hilfe!
Gruss nate
-
Du inkludierst cpp Dateien? -> Autsch.
Man inkludiert nur Header Dateien. Die cpp Dateien werden einfach alle dem Compiler übergeben.
-
1. Wenn du die Destruktoren auch implementierst und nur die main.cpp kompilierst (z.B. mit g++ main.cpp) wird es funktionieren.
2. Dein Fehler ist, dass du alle .cpp Dateien separat kompilierst, diese sich jedoch gegenseitig includen, so dass manche Sachen doppelt und dreifach kompiliert werden.
3. Es ist nicht üblich .cpp Dateien zu includen. Normalerweise werden nur .h Dateien included. Darin hast du schon schöne Include-Guards, die verhindern, dass etwas doppelt definiert wird, wenn es zweimal included wird. Wenn du nur die Header-Dateien mit den Deklarationen includest, wird es funktionieren die .cpp Dateien zu kompilieren und linken.
#ifndef vector_included #define vector_included #include <vector> using namespace std; #endif
Solche Guards sind selten verbreitet und bringen nicht sehr viel Kompilierzeitverbesserung. Ich würde es einfach sein lassen.
-
hey, jungs
ihr seid genial! man schreibt hier was rein, und ne halbe stunde später hat man so hilfreiche antworten, cOOl!mir sind da natürlich mal ganz schön die augen aufgegangen.. hab den doofen fehler gemacht, und das projekt nicht laufend vollständig kompiliert, sondern immer nur einzelne teile davon -> werd ich ändern.
gruss nate
-
nächstes problem (immer noch "multiple definition")
multiple definition of `CVertex::TotalVNr' multiple definition of `CVertex::TotalVNr' ... [Linker error] undefined reference to `CDijkstra::~CDijkstra()' [Linker error] undefined reference to `CDijkstra::~CDijkstra()' [Linker error] undefined reference to `CVertex::~CVertex()' [Linker error] undefined reference to `CVertex::~CVertex()' ...
neue IncludierStruktur ("->" = "wird includiert von"):
Edge.h -> Vertex.h -> Graph.h -> Dijkstra.h -> ReadFromTxt.h -> WriteToTxt.h -> Main.cpp
Jedes .cpp includiert auch noch das zugehörige .hdas ganze projekt auf: http://www.nrg.to/ultinate/PathFinder_v0.2.htm (wenn der server nicht gerade down ist..)
ist das nicht traurig? (*mitleid-suchend*) :p
nee.. also die frage: was läuft hier (immer noch) schief?
-
nate7 schrieb:
nächstes problem (immer noch "multiple definition")
Hast du dir Punkt 1 in meinem Posting durchgelesen? Wenn man die Dinger nicht implementiert, werden die auch nicht gefunden.
int CVertex::TotalVNr = 0;
gehört in die .cpp Datei, da dies eine Definition ist und somit jedesmal wenn vertex.h included wird neu definiert wird.
-
hast du include guards in deinen .h dateien?
#ifndef BLABLA_H #define BLABLA_H // ... // ... #endif
Das verhindert Mehrfacheinbindungen.
MFG
Chris
-
Ponto schrieb:
Hast du dir Punkt 1 in meinem Posting durchgelesen? Wenn man die Dinger nicht implementiert, werden die auch nicht gefunden.
ja, du hast recht. das hab ich voll vergessen.
Ponto schrieb:
int CVertex::TotalVNr = 0;
gehört in die .cpp Datei, da dies eine Definition ist und somit jedesmal wenn vertex.h included wird neu definiert wird.
versteh ich nicht, denn mit meinen include-guards sollte vertex.h ja nur einmal includiert werden. (?)
@Zyrian / Chris: jep, habe ich. siehe: http://www.nrg.to/ultinate/PathFinder_v0.2.htm (Link geht wieder..)
-
versteh ich nicht, denn mit meinen include-guards sollte vertex.h ja nur einmal includiert werden. (?)
aber nur einmal pro übersetzungseinheit.
und damit wird CVertex::TotalVNr mehrfach definiert.
weiterführend:
http://tutorial.schornboeck.net/uebersetzungseinheiten.htm
http://tutorial.schornboeck.net/glossar.htm unter ODR
http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=ODR
-
ja, ok, das tönt einleuchtend.
aber jetzt hab ich die definition der static Variablen so gemacht:
// vertex.cpp: implementation of the CVertex class. // ////////////////////////////////////////////////////////////////////// #include "vertex.h" ////////////////////////////////////////////////////////////////////// // Definition von Static-Membern ////////////////////////////////////////////////////////////////////// #ifndef TOTALVNR #define TOTALVNR int CVertex::TotalVNr = 0; #endif // TOTALVNR ////////////////////////////////////////////////////////////////////// // Konstruktion/Destruktion ////////////////////////////////////////////////////////////////////// CVertex::CVertex() { ++TotalVNr; VNr_ = TotalVNr; //TotalDistance_ = MAX_DOUBLE; } CVertex::~CVertex() { } ...
Wieder bekomm ich die selbe Fehlermeldung (multiple definition of `CVertex::TotalVNr'). Wieso?
Danke im Voraus, nate
-
Du musst verstehn wie das ganze arbeitet:
Jede cpp-Datei, die Du dem Compiler übergibts, ist ein Modul.
Da läuft der Parser drüber. Der Parser ersetzt die includes durch den Text, der in jedem Header steht.
Damit hast Du also praktisch keine Header mehr, sondern nur noch cpp-Dateien (= fertig geparste Module).
Jetzt übersetzt der Compiler jedes Modul.
Dann setzt der Linker die Module zusammen, d.h. er schaut, wie die Module anhand der Deklarationen (=bekanntmachungen von Variablennamen etc.) mit den Definitionen (da wird speicher reserviert) zusammenpassen.Jetzt steht bei Dir die Definition von int CVertex::TotalVNr in jedem einzelnen Modul drinnen -> er weiß nicht welchen er nehmen soll
-
Juppie! es funktioniert!
@alle: dankeschön für die hilfe
greez nate
-thread geschlossen-