Der Compiler generiert Code für jede Vorlageninstanziierung, wenn Sie während des Kompilierungsschritts eine Vorlage verwenden. Beim Kompilieren und Verknüpfen werden CPP-Dateien in reinen Objekt- oder Maschinencode konvertiert, der Verweise oder undefinierte Symbole enthält, da die in Ihrer main.cpp enthaltenen .h-Dateien NOCH keine Implementierung haben. Diese können mit einer anderen Objektdatei verknüpft werden, die eine Implementierung für Ihre Vorlage definiert, sodass Sie über eine vollständige ausführbare Datei verfügen.
Da Vorlagen jedoch im Kompilierungsschritt verarbeitet werden müssen, um Code für jede von Ihnen definierte Vorlageninstanziierung zu generieren, funktioniert das einfache Kompilieren einer Vorlage, die von der Header-Datei getrennt ist, nicht, da sie aus genau diesem Grund immer Hand in Hand gehen dass jede Vorlageninstanziierung buchstäblich eine ganz neue Klasse ist. In einer regulären Klasse können Sie .h und .cpp trennen, da .h eine Blaupause dieser Klasse ist und .cpp die Rohimplementierung ist, sodass alle Implementierungsdateien regelmäßig kompiliert und verknüpft werden können. Die Verwendung von Vorlagen .h ist jedoch eine Blaupause dafür, wie Die Klasse sollte nicht so aussehen, wie das Objekt aussehen soll, was bedeutet, dass eine .cpp-Vorlagendatei keine reguläre Rohimplementierung einer Klasse ist, sondern lediglich eine Blaupause für eine Klasse. Daher kann jede Implementierung einer .h-Vorlagendatei '
Daher werden Vorlagen niemals separat kompiliert und nur dort kompiliert, wo Sie eine konkrete Instanziierung in einer anderen Quelldatei haben. Die konkrete Instanziierung muss jedoch die Implementierung der Vorlagendatei kennen, da einfach die geändert werden musstypename T
Die Verwendung eines konkreten Typs in der .h-Datei wird den Job nicht erledigen, da die zu verknüpfende .cpp-Datei später nicht mehr gefunden werden kann, da die Erinnerungsvorlagen abstrakt sind und nicht kompiliert werden können. Daher bin ich gezwungen Um die Implementierung jetzt zu geben, damit ich weiß, was zu kompilieren und zu verknüpfen ist, und jetzt, wo ich die Implementierung habe, wird sie in die beiliegende Quelldatei verknüpft. Grundsätzlich muss ich in dem Moment, in dem ich eine Vorlage instanziiere, eine ganz neue Klasse erstellen, und das kann ich nicht, wenn ich nicht weiß, wie diese Klasse aussehen soll, wenn ich den von mir bereitgestellten Typ verwende, es sei denn, ich benachrichtige den Compiler von Die Vorlagenimplementierung, sodass der Compiler jetzt durch T
meinen Typ ersetzen und eine konkrete Klasse erstellen kann, die zum Kompilieren und Verknüpfen bereit ist.
Zusammenfassend sind Vorlagen Blaupausen für das Aussehen von Klassen, Klassen Blaupausen für das Aussehen eines Objekts. Ich kann Vorlagen nicht getrennt von ihrer konkreten Instanziierung kompilieren, da der Compiler nur konkrete Typen kompiliert, dh Vorlagen, zumindest in C ++, sind reine Sprachabstraktion. Wir müssen Vorlagen sozusagen de-abstrahieren, und wir geben ihnen einen konkreten Typ, damit unsere Vorlagenabstraktion in eine reguläre Klassendatei umgewandelt und normal kompiliert werden kann. Das Trennen der .h-Datei der Vorlage und der .cpp-Datei der Vorlage ist bedeutungslos. Es ist unsinnig, weil die Trennung von .cpp und .h nur dort erfolgt, wo die .cpp einzeln kompiliert und einzeln mit Vorlagen verknüpft werden kann, da wir sie nicht separat kompilieren können, da Vorlagen eine Abstraktion sind.
Das heißt, typename T
get wird während des Kompilierungsschritts ersetzt, nicht der Verknüpfungsschritt. Wenn ich also versuche, eine Vorlage zu kompilieren, ohne T
als konkreter Werttyp ersetzt zu werden, der für den Compiler völlig bedeutungslos ist und daher kein Objektcode erstellt werden kann, weil dies nicht der Fall ist weiß was T
ist.
Es ist technisch möglich, eine Art von Funktionalität zu erstellen, mit der die Datei template.cpp gespeichert und die Typen ausgetauscht werden, wenn sie in anderen Quellen gefunden werden. Ich denke, dass der Standard ein Schlüsselwort enthält export
, mit dem Sie Vorlagen in eine separate Datei einfügen können cpp-Datei, aber nicht so viele Compiler implementieren dies tatsächlich.
Nur eine Randnotiz: Wenn Sie Spezialisierungen für eine Vorlagenklasse vornehmen, können Sie den Header von der Implementierung trennen, da eine Spezialisierung per Definition bedeutet, dass ich mich auf einen konkreten Typ spezialisiere, der einzeln kompiliert und verknüpft werden kann.