2009-03-08 10 views
8

Ich kompiliere eine C++ statische Bibliothek und da alle Klassen Vorlagen sind, sind die Klassendefinitionen und Implementierungen alle in Header-Dateien. Als Ergebnis scheint es (unter Visual Studio 2005), dass ich eine .cpp-Datei erstellen muss, die alle anderen Header-Dateien enthält, damit sie korrekt in die Bibliothek kompiliert werden kann.Kompilieren einer C++ .lib mit nur Header-Dateien?

Warum ist das?

Antwort

8

Der Compiler kompiliert Header-Dateien nicht, da diese in Quelldateien enthalten sein sollen. Bevor eine Kompilierung stattfindet, nimmt der Präprozessor den gesamten Code aus allen enthaltenen Header-Dateien und speichert diesen Code in den Quelldateien, in denen sie enthalten sind, genau an dem Ort, an dem sie enthalten sind. Wenn der Compiler auch die Header-Dateien kompiliert, haben Sie zum Beispiel mehrere Definitionen für viele Dinge.

Beispiel, das ist, was der Präprozessor sieht:

[foo.h] 
void foo(); 

-

[mysource.cpp] 
#include "foo.h" 

int main() 
{ 
    foo(); 
} 

Und das ist, was der Compiler sieht:

[mysource.cpp] 
void foo(); 

int main() 
{ 
    foo(); 
} 
0

Denken Sie an Standardvorlagenbibliothek Ihre Vorlagen werden kompiliert, wenn Sie sie in einem anderen Projekt verwenden.

0

Was andere gesagt haben, gilt auch für Vorlagen, die nicht in die Bibliothek kompiliert werden. Es lohnt sich jedoch immer noch, sie vom Compiler zu sehen (indem man sie in eine CPP-Datei einfügt), damit sie zumindest auf Syntax überprüft werden.

+0

Es ist besser, eine Reihe von Komponententests zu schreiben, als die Erstellung einer statischen Bibliothek zu erzwingen, die nicht unbedingt vorhanden sein muss. Schließlich werden viele Compiler sehr grundlegende Fehler im Vorlagencode verpassen, wenn dieser Vorlagencode nicht aufgerufen wird. – Tom

2

In C++ sind Vorlagen nur eine Meta-Definition einer tatsächlichen Klasse. Wenn Sie eine Vorlagenklasse kompilieren, generiert der Compiler tatsächlich den Code für die aktuelle Klasse für den bestimmten Typ der Daten, die übergeben werden (die Vorlage ist nur ein zu kopierendes "Muster").

z.B. Wenn Sie den folgenden Code haben

 

struct MyTemplate 
{ 
private: 
    float MyValue; 

public: 
    float Get() { return MyValue; } 
    void Set(float value) { MyValue = value; } 
}; 

void main() 
{ 
    MyTemplate v1; 
    MyTemplate v2; 
    v1.Set(5.0f); 
    v2.Set(2); 
    v2.Get(); 
} 
 

Was ist eigentlich der Compiler sieht, ist

 

struct CompilerGeneratedNameFor_MyTemplate_float 
{ 
private: 
    float MyValue; 

public: 
    float Get() { return MyValue; } 
    void Set(float value) { MyValue = value; } 
}; 

struct CompilerGeneratedNameFor_MyTemplate_int 
{ 
private: 
    int MyValue; 

public: 
    int Get() { return MyValue; } 
    void Set(int value) { MyValue = value; } 
}; 

void main() 
{ 
    CompilerGeneratedNameFor_MyTemplate_float v1; 
    CompilerGeneratedNameFor_MyTemplate_int v2; 
    v1.Set(5.0f); 
    v2.Set(2); 
    v2.Get(); 
} 
 

Wie Sie wahrscheinlich sehen können, ist der Compiler nicht wirklich wissen, was Code zu generieren, bis Sie tatsächlich eine Instanz deklarieren deiner Vorlage. Dies bedeutet, dass die Vorlage nicht in eine Bibliothek kompiliert werden kann, weil sie nicht weiß, was die Vorlage tatsächlich sein wird. Die gute Nachricht dabei ist, dass Sie eigentlich keine Bibliothek kompilieren oder einbeziehen müssen, wenn Sie nur die Headerdateien verteilen, die die Vorlagendefinition enthalten.

Auch, als eine Randnotiz, sagt der '# include' Pre-Compiler-Befehl eigentlich nur den Pre-Compiler das '# include' mit allem aus dieser Datei zu ersetzen.

1

Sie versuchen, etwas unnötiges zu erstellen. Die meisten C-Bibliotheken (und alle C++ Bibliotheken) erhalten als zwei Portionen verteilt:

  • Interface (foo.h)
  • Implementation (foo.lib)

Für C++ Template-Code, alle Ihre Bibliothek muss kompiliert werden, von Ihren Endbenutzern, denn so funktionieren Templates. Es gibt keinen Grund, eine vorkompilierte Bibliothek bereitzustellen. In diesem Fall können Sie Ihre denken Sie an Ihre Bibliothek Verteilung wie folgt aus:

  • Interface (foo.h)
  • Implementation (foo-inl.h)

Wie Niel oben gesagt, ist es nützlich, Implementierungen müssen nur für Ihre eigene Testzwecke, und es lohnt sich wahrscheinlich, diese mit der Bibliothek selbst zu verteilen. Sie sollten also eine separate Suite von Komponententests haben, die Ihren Code auswerten; aber diese Tests sollten nicht Teil der Bibliothek selbst sein.

0

Sie müssen keine .lib generieren, wenn alle Klassen Vorlagen sind, schauen Sie sich einen Boost an oder den Punkt, an dem sie keine .lib haben, die sie verteilen [1].

Vorlagen werden kompiliert, wenn sie verwendet werden.

[1] Genau genommen verteilen sie Bibliotheken für die fortgeschritteneren Funktionen wie reguläre Ausdrücke, Iostream usw., aber Hilfs-Bibliotheken werden von anderen Vorlagen verwendet, die Vorlagen selbst sind nicht in Bibliotheksform verteilt.

2

Wenn sich Ihr gesamter Code in .h-Dateien befindet, müssen Sie keine statische Bibliothek kompilieren, um den Code zu verwenden.

Der gesamte Code ist für die Verwendung der Bibliothek zum Zeitpunkt der Kompilierung verfügbar, sodass zum Zeitpunkt der Verknüpfung nichts benötigt wird.

1

Wenn Ihre Bibliothek vollständig in Headerdateien implementiert ist, müssen Sie keine Binärdatei erstellen, um sie zu verwenden. Das gesagt. Ich erstelle normalerweise eine .cpp-Datei während meiner anfänglichen Entwicklungsphase der Nur-Header-Bibliothek. Warum? Compiler versuchen nicht, Ihre Vorlage zu kompilieren oder gar zu parsen, bis sie tatsächlich verwendet wird. Wenn Sie eine CPP-Datei haben und dort Dummy-Code zum Instanziieren der Templates haben, kann ich Syntaxfehler früher während der Entwicklung finden. So kann ich einen Template-Code hinzufügen, den Kompiliervorgang starten, den Syntaxfehler korrigieren, mehr Code hinzufügen, ... kompilieren. Wenn Sie versuchen, einige dumme Syntaxfehler nach dem Hinzufügen von Hunderten von Codezeilen zu finden, werden Sie wissen, was ich meine. Sobald meine Bibliothek für den Komponententest bereit ist, entferne ich die .cpp-Datei und verlasse mich auf Unit-Tests, um meine Entwicklung voranzutreiben.

Wenn Sie Ihren Code nur mit VC++ kompilieren, müssen Sie sich darüber im Klaren sein, dass VC++ nicht versucht, alle Vorlagenelementfunktionen zu kompilieren, bis sie tatsächlich verwendet werden. Beispiel:

Die f() wird nur gut mit VC++ 2003 kompilieren, g ++ wird den Syntaxfehler abfangen. Ich denke, VC8 und VC9 haben auch das gleiche Problem.

Verwandte Themen