Template Classes - Function definition in seperate file



  • Moinsen!

    Ich habe gerade gelernt, wie man class templates verwenden kann. Um mir das ganze nun einzuprägen bin ich gerade etwas am experimentieren. Dabei bin ich auf ein Problem gestossen.

    Ich habe folgenden Code:

    // template_inheritance_0.cpp
    
    #ifndef TEMPLATE_INHERITANCE_0
    #define TEMPLATE_INHERITANCE_0
    
    #include <iostream>
    #include <string>
    
    template <typename Type>
    class Shape3D  //abstract base class
    {
    private:
    	std::string name;
    
    public:
    
    	Shape3D(std::string name) {this->name = name;}
    	virtual ~Shape3D() = 0;
    
    	virtual Type surface() = 0;
    	virtual Type volume() = 0;
    
    	std::string get_name() {return name;}
    };
    
    template <typename T>
    class Sphere3D : public Shape3D<T>
    {
    private:
    	T radius;
    
    public:
    
    	Sphere3D(T rad = 0, std::string name = "Sphere3D") : Shape3D(name)
    	{
    		radius = rad;
    	}
    
    	~Sphere3D() {}
    
    	T surface();	// function prototype
    	T volume();		// function prototype
    };
    
    #endif
    

    Ich habe nun versucht die beiden functions surface() und volume() in einem seperaten file zu implementieren, so dass in der Klasse Sphere3D selber nur die prototypes vorhanden sind.

    Wie müsste so ein seperates file aussehen? Ich habe es auf viele verschiedene Arten versucht, habe es aber nicht geschafft.



  • Bei teamplates kannst du keine Auslagerung in die .cpp machen.
    Du musst alles im Header definieren. (Du kannst natürilch ein seperates File machen, dass z.B .imp nennen und dann am Ende des Headers includen.



  • Genau das hatte ich vor.

    Mir ist allerdings unklar wie die Syntax aussehen muss in dem seperaten header-file.

    Mein seperates header-file sieht so aus:

    // sphere3d.inl
    
    template <typename T>
    T Sphere3D::surface() {return radius * 10;}
    
    template <typename T>
    T Sphere3D::volume()	{return radius / 10;}
    

    Das scheint aber falsch zu sein. Könntest du mir bitte den Code für eine der beiden Methoden geben? Ich hänge da gerade etwas fest.


  • Mod

    template <typename T>
    T Sphere3D<T>::surface() {return radius * 10;}
    
    template <typename T>
    T Sphere3D<T>::volume()    {return radius / 10;}
    


  • Das ist merkwürdig... ich hatte den Code auch genau so und trotzdem hatte es nicht funktioniert.

    Vielen Dank euch, jetzt weiss ich zumindest, dass das .inl-file korrekt ist. Dann muss ich wohl sonstwo noch Fehler suchen.

    Danke euch.



  • Hast du den include im Header gemacht?



  • Jop, hier die inlucdes:

    #include <iostream>
    #include <string>
    
    #include "sphere3d.inl"
    

    *Edit
    Die Fehlermeldung:

    error C2653: 'Sphere3D' : is not a class or namespace name

    (Gibt noch ne zweite, die identisch ist)



  • Den include musst du NACH der Klassenbeschreibung machen.



  • Ou, das habe ich ja ganz vergessen 😕 Aber jetzt funktionierts 🙂

    Danke für die Hilfe.



  • Ich habe mir das ganze nochmal überlegt und mich gefragt wiso die #includes am Ende des files kommen müssen.

    Ich habe mir das so erklärt, dass zuerst die Prototypen der Funktionen bekannt sein müssen, bevor die implementierte Funktion geladen wird.

    Stimmt das so in etwa? Wie werden header-files eigentlich geladen? Durch die Laufzeitumgebung? Weil sie werden ja nicht kompiliert.



  • icarus2 schrieb:

    Ich habe mir das so erklärt, dass zuerst die Prototypen der Funktionen bekannt sein müssen, bevor die implementierte Funktion geladen wird.

    Nicht geladen, aber definiert.

    icarus2 schrieb:

    Weil sie werden ja nicht kompiliert.

    Doch, werden sie.



  • Also stimmt meine Aussage, wenn man die richtigen Begriffe einsetzt? ^^

    Ich dachte header-files werden nicht kompiliert, weil man bei der IDE Visual C++ nicht einzeln header-files kompilieren kann.



  • icarus2 schrieb:

    Ich dachte header-files werden nicht kompiliert, weil man bei der IDE Visual C++ nicht einzeln header-files kompilieren kann.

    Doch, sie werden auch kompiliert. Allerdings geschieht das indirekt, indem sie über die .cpp-Dateien inkludiert werden.

    Vor dem eigentlichen Kompiliervorgang tut der Präprozessor sein Werk. Der löst unter anderem die Präprozessordirektiven ( #include , #define , #ifdef etc.) auf und ersetzt Makros. Bei #include wird gerade der gesamte Inhalt der angegebenen Headerdatei an die Stelle im Code gesetzt, wo die #include -Direktive steht. Wenn der Compiler beginnt, weiss er nichts mehr über Headerdateien, sondern kompiliert lediglich eine oder mehrere (vergrösserte) Implementierungsdateien.



  • Achso, jetzt ist mir klar, warum header-files nicht einzeln kompiliert werden können.

    Danke für die Info.


Anmelden zum Antworten