FunktionsTemplates in KlassenTemplates



  • Hi Leute 😉 ,

    ich hab mal ne Frage zu Templates wie der Titel schon verrät ;-).
    Ich ein eigenes kleines KlassenTemplate geschrieben(zur Übung weil ich grad c++ lern), in diesem KlassenTemplate hab ich ein FunktionsTemplate deklariert.
    KlassenTemplates und FunktionsTemplates für sich alleine funktionieren aber gemixt klappt gar nichts mehr!

    Hier mal mein code in der cpp Datei :

    #include <iostream>
    #include "Demo.h"
    using namespace std;
    
    void main()
    {
    	Demo<int> Test;
    
    	Test.berechne();
    
    }
    

    Und dies ist der Code der Demo.h:

    template<class cT> class Demo
    {
    	private:
    
    	public:
    
    		Demo(){}
    		~Demo(){}
    
    		template<class fT> fT berechne();
    
    		cT var2;
    };
    
    template<class cT> template<class fT>Demo<cT>::berechne()
    {
    	fT ergebnis = var1 + var2;
    
    	cout << ergebnis << endl;
    
    	return ergebnis;
    
    }
    

    Ich hab den Code aus dem C / C++ Kompendium abgetippt,
    Tippfehler sind keine drin aber es funktioniert trotzdem nich.

    Wäre Klasse wenn ihr mir helfen könntet und mir sagen könntet wie ich FunktionsTemplates ausserhalb von KlassenTemplates richtig definiere und in der main richtig aufrufe.

    ..vorab schon mal vielen Dank für eure Mühe 🙂

    ShadowEater



  • ShadowEater schrieb:

    ...

    ...
    	Demo<int> Test;
    
    	Test.berechne();
    ...
    

    Und dies ist der Code der Demo.h:

    template<class cT> class Demo
    {
    ...
    		template<class fT> fT berechne();
    ...
    

    Der Typ fT ist unbestimmt !

    Bedenke: Du hast 2 Typen:
    cT : KlassenTyp
    fT : FunktionsTyp

    cT legst Du in der Deklaration von Test fest (int) und
    fT könnte er sich aus Parametern von berechne() erschließen ... wenn sie denn welche hätte (bei Klassen geht diese "automatische Bestimmung" aber nicht).
    So musst Du angeben, welche Funktion Du mit Test.berechne() aufrufen willst.
    z.B. Test.berechne<long>();

    Du definierst eine Gruppe von Klassen (für jeden Typ von var eine), von denen jede eine Gruppe von Funktionen enthalten kann (jeweils für jeden Rückgabetyp von berechne() eine).

    Ein ähnliches (aber besseres ;)) Beispiel:

    template<class cT> class Demo
    {
        public:
            template<class fT> fT berechne(fT arg);
            cT var2;
    };
    

    Damit kannst Du für jede "Demo-Variante" (abhängig vom Typ cT) einen ganzen Satz von berechne()-Funktionen erzeugen:

    int main() {
        Demo<int> intDemo;
        Demo<string> strDemo;
        string s;
    
        intDemo.berechne<int>(1);
        intDemo.berechne(2); // macht dasselbe: Automatische Typbestimmung
        intDemo.berechne(s);
    
        strDemo.berechne(s);
        strDemo.berechne(3);
        return 0;
    }
    

    Hiermit erzeugst Du 2 Objekte unterschiedlicher Klassen (Demo<int> und Demo<string>), von denen jede 2 unterschiedliche Funktionen (berechne<int>() und berechne<string>()) besitzen ....

    Gruß,

    Simon2.



  • Und außerdem fehlt bei der Definition der Methode noch die Angabe des Rückgabewerts.



  • Nachtrag: Per Ausprobieren scheint es mir so, dass ein "overloading per Returntyp" bei templates erlaubt ist - was man ohne templates nicht darf. 😮
    Stimmt das ?

    Beispiel:

    class A {
       public:
       template <typename T> T f() { 
          T intern('s'); 
          cout << "f(void): " << intern << "\n"; 
          return intern;
       }
    // int g() { cout << "g()::"; return f<int>(); }
    // char g() { cout << "g()::"; return f<char>(); }
    };
    
    int main() {
       A a;
       a.f<int>();
       a.f<char>();
    	return 0;
    }
    

    funktioniert tadellos und liefert die erwarteten

    f(void): 115
    f(void): s

    Die auskommentierten Zeilen dürfen (verständlicherweise) nicht sein.
    Macht der der gcc einfach, "weil er's kann" (schließlich sage ihm ja, welche Funktion ich haben will, während er bei g() natürlich nicht wissen kann, welchen Typ ich gerne zurückhätte)....
    Oder ist der da standardkonform ?

    GPC schrieb:

    Und außerdem fehlt bei der Definition der Methode noch die Angabe des Rückgabewerts.

    Stimmt natürlich - ist mir aber gar nicht aufgefallen...

    Gruß,

    Simon2.



  • Ja, das ist erlaubt, ist aber kein Overloading mehr. Du hast eine Template-Funktion und entscheidest dich dann explizit für eine Spezialisierung dieser Funktion (dadurch, daß du den Template-Parameter f<int> etc angibst, legst du die Instanz fest).
    Aber genauso wie bei "normalen" Funktionen kann der Compiler nicht aus dem (vermuteten) Rückgabetyp entscheiden, welche Spezialisierung er verwenden soll.



  • CStoll schrieb:

    Ja, das ist erlaubt, ist aber kein Overloading mehr....

    Ach so !
    Dann ist also das:

    class A {
       public:
       template <typename T> T f() { ... }
    };
    

    nicht vergleichbar mit

    class A {
       public:
       int f() { ... }
       char f() { ... } // nicht erlaubt !!
    };
    

    sondern eher mit

    class A {
       public:
       int f_int() { ... }
       char f_char() { ... }
    };
    

    💡 💡

    ist irgendwie auch logisch (und ist sich sogar syntaktisch sehr ähnlich).
    Hach schön: Man lernt nie aus !! C++ ist einfach die beste aller Sprachen !!! :xmas2:

    Danke,

    Simon2.



  • D*A*N*K*E* 👍 😋

    sry dass ich nicht früher aufgetaucht bin aber ich war echt im Stress !

    Danke nochmal, ihr seig die BESTEN 👍 👍 👍 😉

    ShadowEater 😉


Anmelden zum Antworten