Fragen zu Templates



  • Hallo,

    ich versuche (zum 1. mal) mit Templates zu arbeiten.
    Zum Test wollte ich eine Klasse "test" schreiben, die einfach nur ein Objekt der klasse "meine" aufnehmen und wieder zurückgeben kann.

    Ich habe es folgendermaßen versucht:

    #include "stdafx.h"
    #include "iostream.h"
    
    class meine {
    public:
    	meine() {}
    
        void sage() {
    	cout << "bis hier hin gehts";
    	}
    
    };
    
    template<class T>  class test{
    	private:
    		T *data;
    	public:
    		test(T);
    		T get(void); 
    		void set(T);
    
    };
    
    template <class T> test<T>::test(T& t1) {
    
         data = t1;
    }
    
    template <class T>T test<T>::get(void) {
         return *data;
    }
    
    template <class T>void test<T>::set(T& t1) {
    
    	data=t1;
    
    }
    
    int main(int argc, char* argv[])
    {	meine* k = new meine;
         k->sage();
    
        test<meine> l(k) ;
    
    	return 0;
    }
    

    Jedoch kommen Fehler insbesondere im Konstruktor:
    G:\test templates\test templates.cpp(33) : error C2244: 'test<T>::test<T>::test<T>' : Funktionsueberladung kann nicht aufgeloest werden
    G:\test templates\test templates.cpp(39) : error C2954: Vorlagendefinitionen koennen nicht verschachtelt werden
    G:\test templates\test templates.cpp(48) : error C2244: 'test<T>::set' : Funktionsueberladung kann nicht aufgeloest werden
    G:\test templates\test templates.cpp(57) : error C2514: 'test<class meine>' : Klasse besitzt keine Konstruktoren
    G:\test templates\test templates.cpp(57) : error C2262: 'l' : Zerstoerung nicht moeglich

    Wie mache ich das richtig?



  • Du hast den Konstruktor des Templates und die set Methode so deklariert, dass sie ein Objekt by value als Argument übernehmen (test(T); void set(T);) und definiert hast du sie so, dass sie Referenzen als Argumente nehmen. Außerdem weist du data, das ein Zeiger auf T ist ein Objekt von Typ T zu (im Konstruktor)

    Die (hoffentlich) Fehlerlose Variante:

    template<class T>  class test{
        private:
            T *data;
        public:
            test(T&);
            T get(void);
            void set(T&);
    
    };
    
    template <class T> test<T>::test(T& t1) {
    
         data = &t1;
    }
    
    template <class T>T test<T>::get(void) {
         return *data;
    }
    
    template <class T>void test<T>::set(T& t1) {
    
        data=&t1;
    
    }
    

    Felix



  • // Das hier:
    test(T); // Konstruktor übernimmt ein T by value
    
    // Passt ja gar nicht auf das hier:
    template <class T>
    test<T>::test(T& t1) // Konstruktor übernimmt ein T by reference
    {
         data = t1;
    }
    

    MfG SideWinder



  • Vielen Dank,
    machmal sieht man die fehlenden & vor lauter * nicht mehr!



  • Tja jetzt habe ich leider nen neuen Fehler, der mir noch weniger sagt:

    #include "stdafx.h"
    #include "iostream.h"
    
    class meine {
    public:
    	meine() {}
    
        void sage() {
    	cout << "bis hier hin gehts";
    	}
    
    };
    
    template<class T>  class test{ 
        private: 
            T *data; 
        public: 
            test(T&); 
            T get(void); 
            void set(T&); 
    
    }; 
    
    template <class T> test<T>::test(T& t1) { 
    
         data = &t1; 
    } 
    
    template <class T>T test<T>::get(void) { 
         return *data; 
    } 
    
    template <class T>void test<T>::set(T& t1) { 
    
        data=&t1; 
    
    } 
    
    int main(int argc, char* argv[])
    {	meine* k = new meine;
        k->sage();
    
        test<meine> l(k) ;
    
    	return 0;
    }
    

    G:\test templates\test templates.cpp(56) : error C2664: '__thiscall test<class meine>::test<class meine>(class meine &)' : Konvertierung des Parameters 1 von 'class meine *' in 'class meine &' nicht moeglich
    Ein Verweis, der nicht auf ein 'const' zeigt, kann nicht an einen Wert gebunden werden, bei dem es sich nicht um einen L-Wert handelt
    Fehler beim Ausführen von cl.exe.

    Kann mir Jemand auch noch bei diesem Problem helfen?



  • Hallo,

    Du übergibst hier

    test<meine> l(k) ;
    

    einen Pointer, du hast aber nur einen Konstruktor der eine Referenz fordert

    template <class T> test<T>::test(T& t1)
    


  • Tach,

    ersetze mal

    test<meine> l(k) ;
    

    durch

    test<meine> l(*k) ;
    

    dann müsste es gehen



  • Ich habe mal auch eine Frage was züglich Templates angeht...

    mein Code:

    //die headerdatei

    //---------------------------------------------------------------------------
    #include <iostream.h>
    #include <conio.h>
    #ifndef Unit2H
    #define Unit2H
    
            template<class VType>
            class Juans_T_Stack
            {
            private:
    
                    VType *data;
    
                    int anzahl;
                    int max_anzahl;
    
            public:
                    Juans_T_Stack(int); //Aufrufen des Konstruktors mit 2 Parametern
                    ~Juans_T_Stack();
    
                    void menu();
                    void bearbeiten();
    
                    bool Push(VType); //legt Element auf Stack
                    VType Pop(void); //holt Element von Stack
                    int Size(void); //zeigt aktuelle Größe des Stacks an
    
            };
    
    //---------------------------------------------------------------------------
    #endif
    
    //und alles was in einer UNIT ist
    
    //------------------------------------------------------------------------------
    #include "Unit2.h"
    //------------------------------------------------------------------------------
    int main(int argc, char* argv[])
    {
    int menu, MaxStack=0, ergebniss;
    char again;
    
                    do
                    {
    
    cout<<"Programm P7A1"<<endl;
    cout<<endl;
    cout<<"::::Hauptmenue::::"<<endl;
    cout<<endl;
    cout<<"(1) Datentype INT"<<endl;
    cout<<"(2) Datentype FLOAT"<<endl;
    cout<<"(3) Datentype STRING"<<endl;
    cout<<"(4) Programmende"<<endl;
    cout<<":";cin>>menu;
    
    //------------------------------------------------------------------------------
    
            if(menu==1)
            {
            cout<<"Bitte die Maximale Anzahl im Stack angeben"<<endl;
            cout<<":";cin>>MaxStack;
    
            Juans_T_Stack<int> I_Stack(MaxStack);
            int Zahlen=0;
    
              for(int i=0; i<MaxStack; i++)
              {
              cout<<"Bitte geben sie die "<<i+1<<" Zahl ein:";
              cin>>Zahlen;
              I_Stack.Push(Zahlen);
              }
    
            clrscr();
    
                    cout<<"Im Stack befinden sich jetzt ihr INT Werte"<<endl;
                    cout<<"Bitte ENTER druecken um IHR Stack zu betrachten"<<endl;
                    cout<<endl;
                    fflush(stdin);
                    getchar();
    
                    for(int i=0; i<MaxStack; i++)
                    {
                    cout<<": "<<(int)(I_Stack.Pop())<<endl;
                    }
    
                    getchar();
            }
    
    //------------------------------------------------------------------------------
    
            if(menu==2)
            {
            cout<<"Bitte die Maximale Anzahl im Stack angeben"<<endl;
            cout<<":";cin>>MaxStack;
    
            Juans_T_Stack<float> F_Stack(MaxStack);
            float Zahlen=0;
    
              for(int i=0; i<MaxStack; i++)
              {
              cout<<"Bitte geben sie die "<<i+1<<" Zahl ein:";
              cin>>Zahlen;
              F_Stack.Push(Zahlen);
              }
    
            clrscr();
    
                    cout<<"Im Stack befinden sich jetzt ihr INT Werte"<<endl;
                    cout<<"Bitte ENTER druecken um IHR Stack zu betrachten"<<endl;
                    cout<<endl;
                    fflush(stdin);
                    getchar();
    
                    for(int i=0; i<MaxStack; i++)
                    {
                    cout<<": "<<(float)(F_Stack.Pop())<<endl;
                    }
    
            }
    
    //------------------------------------------------------------------------------
    
            if(menu==3)
            {
            cout<<"Bitte die Maximale Anzahl im Stack angeben"<<endl;
            cout<<":";cin>>MaxStack;
    
            Juans_T_Stack<string> S_Stack(MaxStack);
            string woerter;
    
              for(int i=0; i<MaxStack; i++)
              {
              cout<<"Bitte geben sie das "<<i+1<<" Wort ein:";
              cin>>woerter;
              S_Stack.Push(woerter);
              }
    
            clrscr();
    
                    cout<<"Im Stack befinden sich jetzt ihr INT Werte"<<endl;
                    cout<<"Bitte ENTER druecken um IHR Stack zu betrachten"<<endl;
                    cout<<endl;
                    fflush(stdin);
                    getchar();
    
                    for(int i=0; i<MaxStack; i++)
                    {
                    cout<<": "<<S_Stack.Pop()<<endl;
                    }
    
            }
    
    //------------------------------------------------------------------------------
    
            if(menu==4)
            {
            break;
            }
    
    //------------------------------------------------------------------------------
    
                    cout<<"Moechten sie zurueck ins Hauptmenu ?<j>? ?"<<endl;
                    fflush(stdin);
                    again=getchar();
                    }while(again=='j');
    
    }
    
    //------------------------------------------------------------------------------
    
    template<class VType>
    Juans_T_Stack<VType>::Juans_T_Stack(int MaxStack)
    {
            anzahl=0;
            data = new(VType[MaxStack]);
            max_anzahl=MaxStack;
    }
    
    template<class VType>
    Juans_T_Stack<VType>::~Juans_T_Stack()
    {
    delete data;
    }
    
    template<class VType>
    bool Juans_T_Stack<VType>::Push(VType HOW)
    
        {
    
            if(anzahl<max_anzahl)
            {
            data[anzahl++]=HOW;
            return(true);
            }
            else
            {
            return(false);
            }
        }
    
    template<class VType>
    VType Juans_T_Stack<VType>::Pop()
    {
    
            if(anzahl>0)
            {
            return(data[--anzahl]);
            }
            else
            {
            return(0);
            }
    
    }
    
    template<class VType>
    void Juans_T_Stack<VType>::bearbeiten()
    {
    }
    

    So es klappt auch alles bis, dass ich wenn ich Strings einschreibe und wieder herauslese, irgendein fehler exeption auftritt!?

    Ich weiss nicht weiter...geht das denn mit den Templates ohne weiteres mit STRINGS?



  • a) Warum verwendest du keine C++ Code-Tags?
    b) Warum sollte ich den ganzen Code durchlesen, du musst dein Problem zusammenfassen und eingrenzen (Debugger oder einfach so lange Sachen weg machen bis es geht), dann kommt man meistens selber auf den Fehler
    c) Warum machst du keinen neuen Thread auf?
    d) Warum verwendest du veraltete Header (iostream.h)
    e) Was meinst du mit STRING? Ich kenne nichts was STRING heißt.
    f) Ich hab doch mal kurz reingelesen (lol)... Allein dass du 3 mal fast den selben Code für verschiede Typen wiederholst zeigt irgendwie dass du das Prinzip von Templates nicht so ganz verstanden hast.



  • Uj immer diese Warum fragen...was ist denn C++ Code Tag?

    Warum ist denn iostream.h veraltet? Was ist denn neuer?
    Ich bin jetzt kein Crack. Das ist hier wohl ne Klausuraufgabe!
    Ich versuche nur das zu verstehen. Aber wieso verwende ich 3 mal den
    gleichen Code? Ich versuche doch nur nen Speicher Dynamisch auf
    Template-Basis zu generieren ohne gleich für jeden Datentyp eine
    Klasse bilden zu müssen. Deswegen gibt es doch diese Klassentemplates!?
    Oder was ich hab jetzt falschgemacht? Erläutere es bitte doch mal?

    Das Problem mit den Strings ist dessen, dass in C++ anstatt Char datentyp
    jetzt auch mit Strings arbeiten kann! Da braucht man nicht extra ein Feld von Char anzulegen! So jetzt versuche ich halt den Stack mit Strings zu füllen!
    Funktioniert auch. Aber beim auslesen, liest er alles aus und gibt dann eine Fehlermeldung die mir total unbekannt ist und mir garnix sagt!

    Exeption der KLasse EaccsessVialoation

    _string.h

    "~basic_string() { _Destroy(this->_M_start, this->_M_finish + 1); }"

    hier soll der Fehler sein! Aber kein plan kann mir jemand helfen?



  • Beim Schreiben einer Nachricht kann man über die kleinen Knöpfchen unter den Smilies Tags angeben. Hast Du Dich noch nie gefragt, wofür der Knopf "C/C++" da ist?
    Damit wird Dein Code deutlich besser lesbar und damit steigt die Chance, dass ihn sich jemand anschaut.

    Mit 3x den gleichen Code meint FireFlow den Code im Hauptprogramm. Das könnte auch durch ein Template erledigt werden.

    Der Stack sollte auch mit std::string funktionieren.

    Ein Fehler:

    template<class VType>
    Juans_T_Stack<VType>::~Juans_T_Stack()
    {
    delete data; // das muss delete [] data heissen
    }
    

    Die Fehlermeldung sagt Dir übrigens, dass Du auf Speicher versuchst zuzugreifen, der nicht Deinem Prozess gehört (Zugriffsverletzung). In Deinem Fall ist wohl der String kaputt. An welcher Stelle tritt die Fehlermeldung auf?



  • sorry das ich mich jetzt erst wieder melde...aber gestern hatte tiscali wohl ein Problem mit den servern oder so. OK also verstanden hab ich jetzt, was das für ein Fehler ist. Aber die Lösung!? Ich versuche es mal mit dem "delete[]data;

    Aber verstehen tue ich nicht, wie ich im menu templates verwenden soll!? Kannst du mir deine Idee mitteilen? Ich bin echt ein anfänger also nicht wieder rummotzen 👍 😋


Anmelden zum Antworten