Template-Klasse, Template-Funktionen und friend-Deklaration



  • Was bedeutet "Es geht leider nicht" genau? Was sagt der Compiler dazu?



  • Also die Funktion sieht jetzt so aus:

    template<typename T> 
       void print()
      {
        print(maxheap);
        print(sortiertes_v);
      }
    

    und der Aufruf so:

    ergebnis.print<char>();
    

    dann sagt er:

    error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall Heapsort<char>::print<char>(class std::vector<char,class std::allocator<char> > const &)" (??print@D@?print@D@?Heapsort@D@@QAEXABV?vector@DV?vector@DV?allocator@D@std@@@std@@@Z)" in Funktion ""public: void __thiscall Heapsort<char>::print<char>(void)" (??print@D@?print@D@?Heapsort@D@@QAEXXZ)".

    und

    fatal error LNK1120: 1 nicht aufgelöste externe Verweise.



  • Naja, er findet jetzt keine Implementierung der print-Funktion, die ein "const std::vector<char>&" verlangt...

    Aber wie du schon sagtest, die template-Sache ist eigentlich völlig unnötig bei dieser Funktion. Alle Funktionen in einem Klassentemplate sind schon implizit von den Template-Parametern der Klasse abhängig, das heißt, solange die Funktion nicht noch von einem anderen Typ abhängen soll, kannst du dir eine template-Methode sparen.



  • Ok, wenn ich jetzt aber schreibe

    void print()
    {
        print(maxheap);
        print(sortiertes_v);
    }
    

    sagt der Compiler mir:

    error C2780: 'void Heapsort<T>::print(const std::vector<T> &)': Erwartet 1 Argumente - 0 unterstützt

    Was muss ich denn da jetzt noch verändert, dass der Aufruf funktioniert-



  • oder noch besser wäre:

    void print() const
    {
        print(maxheap);
        print(sortiertes_v);
    }
    

    aber da kommt auch wieder

    error C2780: 'void Heapsort<T>::print(const std::vector<T> &)': Erwartet 1 Argumente - 0 unterstützt
    1> with
    1> [
    1> T=char
    1> ]



  • Kannst du bitte deinen aktuellen Quelltext nochmal ganz posten? Ich weiß ja nicht, ob du die inkorrekte definition der Methoden außerhalb der Klasse inzwischen schon gefixt hast usw.

    Und irgendwie muss ich auch mal anmerken, dass mir die ganze Klasse mit ihren friend-Funktionen da ziemlich komisch und undurchsichtig anmutet!



  • Also der komplette Quelltext, Header und cpp-Datei

    #ifndef HEAPSORT_H
    #define HEAPSORT_H
    
    #include<assert.h>
    #include<vector>
    #include<iostream>
    
    typedef unsigned int uint; 
    using namespace std;
    
    template<typename T>
    class Heapsort
    {
    
    private:
        vector<T> maxheap;
        vector<T> sortiertes_v;
    
    public:
        Heapsort(vector<T> const& v): sortiertes_v(), maxheap(v) {};
    
        template<typename T> friend void gen_maxheap(vector<T>& v);
    	template<typename T> friend void test_sinken(vector<T>& v, uint i);
        template<typename T> friend void sortieralgo(vector<T> const& v, Heapsort<T>& ergebnis);
        template<typename T> inline void tausche(T& v, T& k);
        template<typename T> inline void print(vector<T> const& v);
    	//template<typename T> friend inline void print(Heapsort<T> const& v);
    
    	void print() const
    	{
        print(maxheap);
        print(sortiertes_v);
    	}
    
    };
    
    template<typename T>
    void gen_maxheap(vector<T>&  v)
    {
        for(int i = (v.size() / 2 - 1) ; i >= 0; i--)
        {
            test_sinken( v, i);
    
        }
    }
    template<typename T>
    void test_sinken(vector<T>& v, uint i)
    {
        while(i <= v.size() / 2 - 1)
        {
            uint kindindex = 2*i + 1;            //Index des linken Kindknotens
            if(kindindex+1 <= v.size()-1)            //Rechtes Kind?
            {
                if(v[kindindex] < v[kindindex+1])
                    kindindex++;
            }
    
            if(v[i] < v[kindindex])
            {
                tausche(v[i], v[kindindex]);
                i = kindindex;
            }
            else
                break;
    
        }
    }
    
    template<typename T>
    void sortieralgo(vector<T> const& v, Heapsort<T>& ergebnis)
    {
        gen_maxheap<T>(ergebnis.maxheap);
        vector<T> w= ergebnis.maxheap;
    
        while(w.size() > 0)
        {
            tausche(w.front(), w.back());
            (ergebnis.sortiertes_v).push_back(w.back());
            w.pop_back();
            if(w.size()==1)
            {
                (ergebnis.sortiertes_v).push_back(w.back());
                w.pop_back();
            }
            else
                test_sinken(w, 0);
        }
    }
    
    template<typename T>
    void tausche(T& v, T& k)
    {
        T temp = v; 
        v = k;
        k = temp;
    };
    
    template<typename T>
    void print(vector<T> const& v)
    {
        for(uint i = 0; i < v.size(); i++)
        {
            cout << v[i] << " " ;
        }
        cout << endl;
    }
    
    //template<typename T>
    //void print(Heapsort<T> const& ergeb)
    //{
    //    print(ergeb.maxheap);
    //    print(ergeb.sortiertes_v);
    //}
    
    #endif
    
    #include<cassert>
    #include<vector>
    #include<iostream>
    #include "Heapsort_Prüfung.h"
    
    using namespace std;
    
    typedef unsigned int uint;
    
    int main()
    {
        vector<char> v;
        v.push_back('H');
        v.push_back('E');
        v.push_back('A');
        v.push_back('P');
        v.push_back('S');
        v.push_back('O');
        v.push_back('R');
        v.push_back('T');
    
        Heapsort<char> ergebnis(v);
        sortieralgo(v,ergebnis);        //Aufruf des sortieralgorithmus
        print(v);
    	ergebnis.print<char>();
    	//print(ergebnis);
        //ergebnis.print<char>();
    
    	system ("pause");
        // cin.get();
        return 0;
    }
    

    was meinst du denn mit undurchsichtig? ich hab halt für die Prüfung versucht möglichst viele Möglichkeiten, die C++ bietet in den Code zu packen, d.h. z.B das mit der friend Deklaration.

    Ich hätte die private Klassenmember auch public machen können, da wäre das um einiges einfacher und ich hätte auch keine Klasse für den ganzen Code gebraucht...so musste ich eben noch zwei Klassenmember "erfinden".



  • So hab grade gemerkt, dass der Aufruf jetzt falsch ist, aber auch wenn ich das korrigiere kommen noch Fehler:

    #include<cassert>
    #include<vector>
    #include<iostream>
    #include "Heapsort_Prüfung.h"
    
    using namespace std;
    
    typedef unsigned int uint;
    
    int main()
    {
        vector<char> v;
        v.push_back('H');
        v.push_back('E');
        v.push_back('A');
        v.push_back('P');
        v.push_back('S');
        v.push_back('O');
        v.push_back('R');
        v.push_back('T');
    
        Heapsort<char> ergebnis(v);
        sortieralgo(v,ergebnis);        //Aufruf des sortieralgorithmus
        print(v);
    	ergebnis.print();
    	//print(ergebnis);
        //ergebnis.print<char>();
    
    	system ("pause");
        // cin.get();
        return 0;
    }
    

    Fehler:

    rror C2663: 'Heapsort<T>::print': für 2 Überladung(en) gibt es keine zulässige Konvertierung für den this-Zeiger
    1> with
    1> [
    1> T=char
    1> ]

    und noch einiges mehr... 😕



  • Wofür ist die Heapsort-Klasse eigentlich gut, wenn du alles mit friend-Funktionen außerhalb der Klasse machst? Ich verstehe den ganzen Ansatz nicht, und warum deklarierst du Funktionen als friends, die gar nicht auf private-member von der Klasse zugreifen?
    Warum benutzt du inline? Warum deklarierst du Member-Funktionen und versuchst sie dann als freie Funktionen zu implementieren?
    Mir tut das im Gehirn weh, wenn ich das da vor mir sehe 😞
    Also was ich meine ist, du hast da noch viel grundlegendere Probleme als nur die Compiler-Fehler, im Moment.



  • Und vor allem: Warum ist Heapsort überhaupt eine Klasse? Wir sind hier nicht bei Java, sondern können auch freie Funktionen definieren.



  • also wäre so besser...

    #include<cassert>
    #include<vector> 
    #include<iostream>
    
    using namespace std;
    
    typedef unsigned int uint;
    
    template<typename T>						//Array vom Typ T zur Sortierung
    void gen_maxheap(vector<T>& v)
    {
    	for(int i = (v.size() / 2 - 1) ; i >= 0; i--)
    	{
    		test_sinken( v, i);
    
    	}
    }
    template<typename T>
    void test_sinken(vector<T>& v, uint i)
    {
    	while(i <= v.size() / 2 - 1)
    	{
    		uint kindindex = 2*i + 1;			//Index des linken Kindknotens
    		if(kindindex+1 <= v.size()-1)			//Rechtes Kind?
    		{
    			if(v[kindindex] < v[kindindex+1])
    				kindindex++;
    		}
    
    		if(v[i] < v[kindindex])
    		{
    			tausche(v[i], v[kindindex]);
    			i = kindindex;
    		}
    		else
    			break;
    
    	}
    }
    
    template<typename T>
    void heapsort(vector<T>& v, vector<T>& sortiertes_v)
    {
    gen_maxheap(v);
    print(v);
    	while(v.size() > 0)
    	{
    		tausche(v.front(), v.back());
    		sortiertes_v.push_back(v.back());
    		v.pop_back();
    		if(v.size()==1)
    		{
    			sortiertes_v.push_back(v.back());
    			v.pop_back();
    		}
    		else
    			test_sinken(v, 0);
    
    	}
    }
    template<typename T>
    void inline tausche(T& v, T& k)
    {
    	T temp = v;
    	v = k;
    	k = temp;
    }
    
    template<typename T>
    void inline print(vector<T> const& v)
    {
    	for(uint i = 0; i < v.size(); i++)
    		{
    			cout << v[i] << " " ;
    		}
    		cout << endl;
    }
    
    int main()
    {
    	vector<char> v;
    	v.push_back('H');
    	v.push_back('E');
    	v.push_back('A');
    	v.push_back('P');
    	v.push_back('S');
    	v.push_back('O');
    	v.push_back('R');
    	v.push_back('T');
    
    	vector<char> sortiertes_v;
    	heapsort(v, sortiertes_v);
    	print(sortiertes_v);
    
    	system ("pause");
    	return 0;
    }
    

    Ich hatte ja schon mal geschrieben, dass das ein Programm ist, was ich zur mündlichen Prüfung mitnehme. Und da habe ich versucht viele c++ Features reinzupacken, d.h. neben Template-Klasse auch Template-Funktionen, include "Header.h", freind-Deklaration um auf private member zuzugreifen usw.
    Den Code den ich jetzt hochgeladen habe der macht im Prinzip das gleiche...nur eben mit weniger Features...



  • Naja, du könntest den Sortier-Algo zB. für den Vergleich (Also die Ordnung template'isieren. Und dann nen Vergleichs-Funktor mitgeben oder sowas.

    Die Ausgabe könntest du durch überladung des << Operators implementieren. Das wäre alles "sinnvoll" und würde zusätzlich noch etwas von C++ zeigen.



  • KISS ... selbe Mächtigkeit mit weniger 'Features' ist doch gut??


Anmelden zum Antworten