2009-03-22 5 views
2

Guten Abend :)g ++ Header enthalten: noch keine Definition

Ich spiele mit g ++ und Makefiles herum. Ich habe zu diesem Punkt gekommen:

foo.h:

#ifndef _FOO_H_ 
#define _FOO_H_ 

#include "bar.h" 

class foo { 
private: 
    bar something; 
public: 
    bool start(); 
    bool stop(); 
}; 

#endif // _FOO_H_ 

foo.h schließlich in meiner Haupt-CPP-Datei enthalten ist, so dass ich die Dinge in Bewegung setzen kann durch lostelefonieren/Stopp.

void somewhere() { 
    foo* hihi = new foo; 
    hihi->start(); 
    delete hihi; 
} 

Dann gibt es bar.h:

#ifndef _BAR_H_ 
#define _BAR_H_ 

class bar { 

}; 

#endif // _BAR_H_ 


g ++ nicht es scheint jedoch zu mögen:

g++ (some_flags) -c main.cpp 
In file included from main.cpp:2: 
foo.h:8: error: ‘bar’ does not name a type 

Ich bin mit Makefiles, und versucht, eine Kombination aus Dinge wie:

main.o: main.cpp foo.h bar.h 

Auch wenn ich nicht denke, dass ich bar.h hier hinzufügen sollte, sollte es nicht in foo.h genug sein?

Um zu klären, dies grob ist, wie es jetzt Set up (ja, ich weiß, dass dies in einer effizienteren Weise getan werden kann):

main.o: main.cpp foo.h 
    $(CC) $(CFLAGS) -c main.cpp 

foo.o: foo.h foo.cpp 
    $(CC) $(CFLAGS) -c foo.cpp 

bar.o: bar.h bar.cpp 
    $(CC) $(CFLAGS) -c bar.cpp 

Was ist los? Ich denke, dass es etwas ist, was ich an g ++ vermisse und die Art und Weise, wie es Header behandelt, schließe mich bitte in die richtige Richtung!

bearbeiten - fand die Lösung:

Doh! Ich fühle mich jetzt dumm. War mit boost :: asio rum und irgendwie vergaß ich noch das oben auf meine Header irgendwo: mit boost :: asio :: ip :: tcp;

Sagen wir einfach, es gibt eine boost :: asio :: ip :: tcp :: bar Funktion: D

Na ja, trotzdem danke!

+0

Sind Sie sicher, dass es die richtige bar.h? GCC 3.4.5 beklage das nicht für mich. –

+1

ein Ratschlag. * Nie * lege eine using-Direktive in eine Kopfzeile. In einer CPP-Datei ist das in Ordnung, aber in einer Kopfzeile verlangst du nur, dass diese Art von Problem auftritt. –

+0

@Evan: Ich werde versuchen, es im Kopf zu behalten, danke. –

Antwort

2

War Herumspielen mit boost :: asio und Art habe ich vergessen, das noch links oben auf meine Header irgendwo: mit boost :: asio :: ip :: tcp;

Sagen wir einfach, es gibt eine boost :: asio :: ip :: tcp :: bar Funktion

Dan Saks explains einige Gründe, warum Sie Ihre Klassennamen typedef sollte, auch wenn es überflüssig erscheinen könnte.

Nun, haben Sie in reale Lebenssituation führen, wo eine Klasse typedefing würde wahrscheinlich Sie Ihr Problem ein wenig finden haben dazu beigetragen, leichter:

class bar { 
// ... 
}; 
typedef class bar bar; 

generiert diese aussagekräftigere Nachricht, wenn es eine Funktion bar() bereits erklärt benannt :

In file included from C:\temp\foo.h:4, 
       from C:\temp\test.cpp:4: 
C:\temp\bar.h:7: error: `typedef class bar bar' redeclared as different kind of symbol 
C:\temp\test.cpp:1: error: previous declaration of `void bar(int)' 
C:\temp\bar.h:7: error: declaration of `typedef class bar bar' 
0

Im main.cpp, müssen Sie die folgende Zeile am Anfang der Datei hinzufügen:

#include "foo.h" 
+0

bar.h ist in foo.h enthalten, das in main.cpp enthalten ist –

+0

Wenn diese Zeile fehlen würde, dann würden wir keine Nachricht über Zeile 8 von foo.h als "Datei aus main.cpp: 2 . " –

1

Doppel alles überprüfen. Wenn Sie bar.h in foo.h einschließen, sollte der Compiler keinen Fehler auslösen. Haben Sie foo.h von bar.h? Tun Sie das besser nicht, weil das eine zirkuläre Abhängigkeit zwischen den Headern verursachen würde, die diese Art von Fehlern verursachen würden.

Überprüfen Sie auch die Schreibweise der Kopfleisten. Dies kann eine häufige Quelle von Ärger sein:

#ifdef _BAR_H_ // OOPS! we wanted #ifndef 
#define _BAR_H_ 

class bar { 

}; 

#endif // _BAR_H_ 

Darüber hinaus sollten Sie den Unterstrich, bevor Sie Ihren Kopf guard Makronamen setzen vermeiden. Diese Namen sind dem Compiler vorbehalten. Nennen Sie es INCLUDED_BAR_H oder einfach nur BAR_H_.

+0

Das war nicht gerade die Lösung für mein Problem, aber +1 für die Info, danke. –

1

Tommy Hui und litb haben bereits auf zwei mögliche Ursachen hingewiesen; Hier sind einige Hintergrundinformationen, die hoffentlich nützlich sein werden.

Zunächst einmal hat dies nichts mit Makefiles zu tun. Ein Makefile ist nur eine Annehmlichkeit, die g ++ für Sie aufruft, mehr nicht.

Dieses Zeug mit Header-Dateien kann ein bisschen schwierig zu verstehen, zunächst einmal, vor allem, wenn Sie in kreisförmige Abhängigkeiten geraten. Es hat mir wirklich geholfen, diese drei Dinge zu erkennen:

  • A #include nichts anderes als ein copy/paste Betrieb ist, zu diesem Zeitpunkt den Inhalt der Datei enthalten einfügen.
  • Alles muss vorher deklariert sein, bevor es verwendet wird. Manchmal, wenn zirkuläre Abhängigkeiten auftreten, müssen Sie möglicherweise eine Klasse (z. B. class bar;) in einer anderen Kopfzeile vorab deklarieren.
  • Wenn zum Zeitpunkt der Verwendung weitere Informationen über den Typ benötigt werden, als nur seine Existenz, dann wird auch die Definition des Typs benötigt. Dies gilt z.B. Aufrufen einer Methode für ein Objekt dieses Typs, aber auch für ein Feld dieses Typs! (Nicht für einen Zeiger auf ein Objekt dieser Art, obwohl, weil Zeiger alle gleich groß sind.)
+0

Das war nicht gerade die Lösung für mein Problem, aber +1 für die Info, danke. –