Template-Klasse, Template-Funktionen und friend-Deklaration



  • 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