2010-09-10 10 views
5

Wie lösen Sie erstellt, indem Sie eine Header-Datei mit dem gleichen Namen wie eine andere Header-Datei bereits indirekt als Ergebnis eines anderen enthalten enthalten?C++: mehrere Header-Dateien mit demselben Namen aus verschiedenen Namespaces enthalten

Zum Beispiel:

// src/blah/a.hpp 
#ifndef A_HPP 
#define A_HPP 

namspace blah 
{ 

class A 
{ 
} 

} 

#endif 

// src/blah/b.hpp 
#ifndef B_HPP 
#define B_HPP 

#includes "a.hpp" 

namspace blah 
{ 

class B 
{ 
} 

} 

#endif 

// src/foo/a.hpp 
#ifndef A_HPP 
#define A_HPP 

namspace foo 
{ 

class A 
{ 
} 

} 

#endif 

// src/foo/c.hpp 
#ifndef C_HPP 
#define C_HPP 

#includes "../b.hpp" 
#includes "a.hpp"  // won't be included due to multiple inclusion prevention 

namspace foo 
{ 

class C 
{ 
} 

} 

#endif 

Im letzten Header-Datei, a.hpp wird nicht wegen der mehrfachen Aufnahme Präprozessor Wachen eingeschlossen werden. Eigentlich sollte das aber in Ordnung sein, da sich die Klassen in verschiedenen Namespaces befinden. Mir ist klar, dass der einfache Weg darin besteht, einfach den Namen foo/a.hpp zu ändern oder ihm einfach einen falschen Namen im Multiple-Inclusion-Guard zu geben. Gibt es einen besseren Weg?

EDIT Ich verstehe, dass Sie dieses Problem, indem Sie einen beschreibenden Namen in den #define und #ifndef Richtlinien (zB FOO_A_HPP und BLAH_A_HPP) lösen kann, aber ich möchte wissen, ob, dass die empfohlene oder beste Weg, . Würden einige Leute empfehlen, einen anderen Dateinamen als eine bessere Lösung zu verwenden, oder spielt es keine Rolle? Würden Sie die Konvention empfehlen die Verwendung von:

<NAMESPACE>_<CLASS>_HPP 

statt

<CLASS>_HPP 

eine bessere Chance zu vermeiden, in der Regel diese Probleme zu geben?

+0

Warum ist dies als C markiert? –

+0

Ich habe den Namensraum immer in meine Wachen gelegt. Automatisierte Tools legen eine GUID als Header Guard fest. Der entscheidende Punkt ist, dass sie ** EINZIGARTIG sein müssen ** (nicht nur in Ihrem Projekt, sondern vorzugsweise einzigartig in allen Dateien auf der ganzen Welt in allen Dimensionen, wenn möglich). –

Antwort

7

Sie diese lösen, einfach, indem sie nicht die gleiche #define an der Spitze mit ...

Es wäre besser, BLAH_A_HPP und FOO_A_HPP usw. zu verwenden, so dass der #define den Namen Namespace enthält auch.

Edit: Nun ich persönlich empfehlen Sie folgendermaßen vorgehen:

1) Haben Sie keine Header nennen die gleiche (dh verwenden unterschiedliche Dateinamen ... dies nicht immer Hilfe) und verschiedene #define Namen verwenden.
2) Benennen Sie Klassen nicht gleich. Setzen Sie 1 Klasse pro Kopf und benennen Sie die Kopfzeile nach der Klasse 3) Wenn sie durch einen Namespace differenziert werden, verwenden Sie diesen Namespace im Dateinamen UND #define 4) Fügen Sie eine ID zu Ihnen #definieren, die für Sie einzigartig ist (Ich könnte GOZ zum Beispiel verwenden)
5) Verwenden Sie #pragma einmal. Es ist nützlich für die Compiler, die es ist.

Es ist alles eine Frage des Geschmacks obwohl. Wählen Sie ein Schema, das für Sie arbeitet und bleiben Sie dabei. Es gibt kein richtig oder falsch. Solange es funktioniert und konsistent ist.

+0

verstanden, siehe meine Bearbeitung für weitere Erläuterungen zu der Frage. Würden Sie die Konvention von NAMESPACE_CLASS_HPP allgemein empfehlen? Ist das besser als nur den Dateinamen zu ändern oder ist das egal? – deuberger

+0

@deuberger: das Ändern des Dateinamens macht keinen Unterschied; Das Problem ist auf den doppelten Namen des Include-Guard zurückzuführen. Und ja, ich würde empfehlen, etwas wie NAMESPACE_CLASS_HPP für den Include-Guard zu verwenden. –

+0

Wahr ist es eine "teilweise Lösung" ... Ich werde es beheben :) – Goz

0

Obwohl es keine Namespaces in C gibt, denke ich, dass dies sowohl für C als auch C++ funktioniert.

#ifndef BLAH_B_HPP 

und

#ifndef FOO_B_HPP 
1

Wenn MSVC eine Klasse erstellt wird es eine GUID zu Ihrem Schutz Namen, diese Art von Problem zu vermeiden.

+0

Nichts sagt hier hes mit MSVC, was sowieso nicht möglich ist seit C++. – alternative

+0

@mathepic: was meinst du, es ist nicht möglich, da es C++ ist, was ist das für ein Unsinn? Geben Sie ein Beispiel für einen Standard Weg, um sicherzustellen, dass Header-Wächter einzigartig ist mit Hintergrund in, woher die Idee kam, nicht sagen, dass die Verwendung von MSVC notwendig ist. –

+0

@mathepic: Nein, es enthält definitiv C++, und das ist immer noch neben dem Punkt. –

0

Wie Sie selbst vorgeschlagen haben, ist der normale Weg, dies zu tun, Ihre Schutzkennungen eindeutig zu machen, indem Sie eine GUID oder einen vollständigen Pfad anhängen, oder was Sie haben.

in VC++ gibt es auch ein pragma Pflege mehrere Aufnahme für Dich zu treffen, so müssen Sie nicht selbst die #if defined(HUMPTYDUMPTY) Bit zu schreiben, es geht wie

#pragma once 

worden ist, um für ein paar Iterationen VC++ jetzt, aber für andere Compiler müssten Sie überprüfen. Dies erspart Ihnen auch die Suche nach eindeutigen Namen.

Bearbeitet: Einfach mal gucken und das Internet denkt, dass dies auch in GCC ist. Scheint, wie die #include Stil Wachen sehr viel des 20. Jahrhunderts sind ...

+0

Guter Punkt, obwohl es wie #pragma im Allgemeinen scheint und #pragma einmal nicht der bevorzugte Weg ist. Siehe: http://stackoverflow.com/questions/787533/is-pragma-once-a-safe-include-guard. – deuberger

+0

Lesen Sie den Beitrag über das Pragma. Ich bin nicht wirklich besorgt über die Leistung hier; nur denken, dass je mehr Sie tippen müssen, desto wahrscheinlicher Sie Fehler machen. Wenn Sie zwischen inkompatiblen Compilern viel Code portieren, kann dies jedoch ein Problem sein. So oder so, ich würde nichts verlieren. –

2

Ich bin überrascht, dass niemand die einfache Lösung des Verwendens #undef A_HPP erwähnt wie unten

//src/foo/c.hpp 
#ifndef C_HPP 
#define C_HPP 

#includes "../b.hpp" 
#undef A_HPP 
#includes "a.hpp" 
... 

Dies ist besonders gut, wenn foo/c.hpp ist die einzige Datei, die man ändern kann oder darf.

+0

Guter Punkt und ich bin jetzt überrascht, dass Sie es erwähnen. – deuberger

Verwandte Themen