Template-Fehler



  • Hallo,
    da ich mich sehr für Informatik im allgemeinen interessiere, habe ich mich nun mal dran gemacht C++ zu lernen.
    Habe mir nun ein Buch gekauft ("Einstieg in Visual C++ 2008" André Willms Verlag: Galileo Computing) in dem alles meiner Meinung nach wirklich gut beschrieben ist und auch Spaß beim lesen macht.

    Bin nun auch schon recht gut in dem Buch und in der Sprache vorrangekommen.
    Nun habe ich aber ein Problem.
    Es geht momentan um Templates. Eigentlich dachte ich ich hätte alles was in dem Kapitel steht verstanden, als ich dann jedoch eine Übung dazu gemacht habe kam ich zu einem Problem.

    Hier erstmal der Code:
    main.cpp

    #include <iostream>
    #include "Becher.h"
    
    int main()
    {
    	Becher<int> b( "Wasser", 500, 50 );
    	b.ausgabe();
    
    	system("Pause");
    	return(EXIT_SUCCESS);
    }
    

    Becher.h

    #pragma once
    
    #include <iostream>
    #include <string>
    
    template<typename T>
    class Becher
    {
    	std::string i;
    	T fa;
    	T fu;
    public:
    	Becher( std::string inhalt, T fassungsvermoegen, T fuellhoehe );
    	T getFuellmenge();
    	void ausgabe();
    };
    

    Becher.cpp

    #include "Becher.h"
    #include <iostream>
    #include <string>
    
    Becher::Becher( std::string inhalt, T fassungsvermoegen, T fuellhoehe )
    : i( inhalt ), fa( fassungsvermoegen ), fu( fuellhoehe )
    {
    }
    
    T Becher::getFuellmenge()
    {
    	return( fa * ( fu / 100.0F ) );
    }
    
    void Becher::ausgabe()
    {
    	std::cout << "Ein Becher mit " << getFuellmenge() << "ml " << i << std::endl;
    }
    

    Und folgenden Fehler erhalte ich beim compilieren:

    1>------ Erstellen gestartet: Projekt: 10.13 Uebung01, Konfiguration: Debug Win32 ------
    1>Kompilieren...
    1>Becher.cpp
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(5) : error C2955: "Becher": Für die Verwendung der template-Klasse ist eine template-Argumentliste erforderlich.
    1>        c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.h(8): Siehe Deklaration von 'Becher'
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(5) : error C2955: "Becher": Für die Verwendung der template-Klasse ist eine template-Argumentliste erforderlich.
    1>        c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.h(8): Siehe Deklaration von 'Becher'
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(5) : error C2061: Syntaxfehler: Bezeichner 'T'
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(6) : error C2509: '{ctor}': Memberfunktion wurde in 'Becher' nicht deklariert
    1>        c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.h(8): Siehe Deklaration von 'Becher'
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(6) : error C2065: 'inhalt': nichtdeklarierter Bezeichner
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(6) : error C2065: 'fassungsvermoegen': nichtdeklarierter Bezeichner
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(6) : error C2065: 'fuellhoehe': nichtdeklarierter Bezeichner
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(10) : error C2955: "Becher": Für die Verwendung der template-Klasse ist eine template-Argumentliste erforderlich.
    1>        c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.h(8): Siehe Deklaration von 'Becher'
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(10) : error C2143: Syntaxfehler: Es fehlt ';' vor 'Becher<T>::getFuellmenge'
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(10) : error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(11) : error C2509: 'getFuellmenge': Memberfunktion wurde in 'Becher' nicht deklariert
    1>        c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.h(8): Siehe Deklaration von 'Becher'
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(15) : error C2955: "Becher": Für die Verwendung der template-Klasse ist eine template-Argumentliste erforderlich.
    1>        c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.h(8): Siehe Deklaration von 'Becher'
    1>c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.cpp(16) : error C2509: 'ausgabe': Memberfunktion wurde in 'Becher' nicht deklariert
    1>        c:\dokumente und einstellungen\xxxxx\eigene dateien\visual studio 2008\projects\beispielevc++2008\10.13 uebung01\becher.h(8): Siehe Deklaration von 'Becher'
    1>main.cpp
    1>Code wird generiert...
    1>Das Buildprotokoll wurde unter "file://c:\Dokumente und Einstellungen\xxxxx\Eigene Dateien\Visual Studio 2008\Projects\BeispieleVC++2008\10.13 Uebung01\Debug\BuildLog.htm" gespeichert.
    1>10.13 Uebung01 - 13 Fehler, 0 Warnung(en)
    ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========
    

    Vorallem mit diesen ganzen C2955 Fehler habe ich eine Problem. Die anderen scheinen daraus zu folgen.

    Über Hilfe würde ich mich freuen.



  • du musst den template deklarationskopf mit in der definition schreiben oder du schreisbt gelich alels in die header datei

    also entweder

    template<typename T>
    class foo
    {
        T getDings(T bar)
        {
           return bar;
        }
    };
    

    oder so

    // foo.h
    template<typename T>
    class foo
    {
        T getDings(T bar);
    };
    
    //foo.cpp
    #include "foo.h"
    template<typename T>
    T foo::getDings(T bar)
    {
        return bar;
    }
    


  • Guten Abend,

    der Compiler muss die Definition in diesem Fall schon gleichzeitig mit der Deklaration sehen.

    D.h. entweder du schreibst alles in den Header, oder lagerst die Definitionen in eine extra Datei (gebräuchlich *.inl, *.tpp) aus, die du dann ein den Header unten einbindest.

    Desweiteren musst du auch bei der Definition angeben, dass du Templates verwendest.

    Bsp:

    template <typename T> struct A
    {
    	void foo(); //Deklaration
    	...
    };
    
    //Definition
    template <typename T>
    void A<T>::foo() {..}
    


  • Erstmal vielen Dank euch beiden.
    Habe die Definition nun nichtmehr ausgelagert sondern in der Headerdatei gepackt und alles klappt wunderbar.

    Dann habe ich jedoch versucht es auch so zum Laufen zu bekommen das es mit ausgelagerter Definition in der becher.cpp Datei klappt.

    Leider klappt das da nun nicht. Mein Buch (was sonst eigentlich wirklich perfekt war aus meiner Sicht) hat zu dem Thema leider nicht besonders viel, deswegen muss ich hier nochmal nachfragen wie das bei ausgelagerter Definition genau klappt.

    ich habe die Header Datei jetzt mal so gelassen und die becher.cpp so geändert:

    #include "Becher.h"
    #include <iostream>
    #include <string>
    template<typename T>
    
    Becher::Becher( std::string inhalt, T fassungsvermoegen, T fuellhoehe )
    : i( inhalt ), fa( fassungsvermoegen ), fu( fuellhoehe )
    {
    }
    
    T Becher::getFuellmenge()
    {
        return( fa * ( fu / 100.0F ) );
    }
    
    void Becher::ausgabe()
    {
        std::cout << "Ein Becher mit " << getFuellmenge() << "ml " << i << std::endl;
    }
    

    Mir würde reichen wenn ihr das ganze so bearbeiten könntet das es klappt falls ihr es schlecht erklären könnt. Das Grundprinzip schein ich wohl verstanden zuhaben, nur bei diesem einen "Sonderfall" hackts noch, mit einer kleinen Veranschaulichung von euch werde ich das aber denke ich verstehen.

    PS: Ihr seit hier ja verdammt schnell mit dem Helfen 😉



  • //becher.tpp (or whatever)
    
    //#include "Becher.h" <--- weg damit
    //#include <iostream>
    //#include <string>
    
    template<typename T>
    Becher<T>::Becher( std::string inhalt, T fassungsvermoegen, T fuellhoehe )
    : i( inhalt ), fa( fassungsvermoegen ), fu( fuellhoehe )
    {
    }
    
    template<typename T>
    T Becher<T>::getFuellmenge()
    {
        return( fa * ( fu / 100.0F ) );
    }
    
    template<typename T>
    void Becher<T>::ausgabe()
    {
        std::cout << "Ein Becher mit " << getFuellmenge() << "ml " << i << std::endl;
    }
    
    //becher.h
    #pragma once
    
    #include <iostream>
    #include <string>
    
    template<typename T>
    class Becher
    {
        std::string i;
        T fa;
        T fu;
    public:
        Becher( std::string inhalt, T fassungsvermoegen, T fuellhoehe );
        T getFuellmenge();
        void ausgabe();
    };	
    
    #include "becher.tpp"
    

    Das war's auch schon. Ein Auslagern in die *.cpp funktioniert nicht (solange export nicht vom Compiler unterstützt wird), weil der Compiler nur den konkreten Template-Code instanziiert, der auch benutzt wird. Da du nur die Header einbindest, und dann Becher mit einem Typ instanziierst, muss er auch die Definition schon zu diesem Zeitpunkt kennen.
    (Hoffe, das einigermassen richtig erklärt zu haben)

    HTH



  • FAQ-Eintrag zu dem zweiten Problem:

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-39467.html

    Felix


Anmelden zum Antworten