Templateproblem
-
Hi,
wenn aus templates ("Schablonen") "richtige" Funktionen/Klassen gemacht werden, nennt man das "instantiiert". Das macht der Compiler für Dich und er zeigt an, welche Zeile im Code ihn dazu veranlassen (das passiert nämlich nur für die Typen und Situationen, in denen sie tatsächlich verwendet werden).
Leider hast Du (wenn ich das richtig lese) den wesentlichen Teil der Fehlermeldung abgeschnitten, so dass ich Dir zu dem einen error nichts sagen kann. Die warnings kommen daher, dass Du tradeoff letztlich als (signed) int deklariert hast ... und es mit size_t (immer unsigned) vergleichst.... (und i genauso).
BTW: warum tradeoff vom Typ T sein sollte, ist mir nicht klar ... es bezeichnet doch auch nur eine Position, oder ?Gruß,
Simon.
-
Die Glaskugel hat CStoll gestohlen, und irgendwie sieht das ganze für T=int harmlos aus; poste doch mal die genaue Fehlermeldung.
-
camper schrieb:
Die Glaskugel hat CStoll gestohlen
Hey, keine Verleumdungen - ich hab' meine eigene Glaskugel.
@Stromberg: Hat es einen Grund, daß du nicht std::sort verwendest?
-
So da bin ich wieder.
@CStoll
Ja kein Plan, ich hab das eher so als Übung gemacht, also nur zum Vergnügen. Außerdem sollte man doch wenn man ein guter Programmierer ist bzw. werden möchte
mindestens einen"simplen" Sortieralgorithmus (schreibt man des so?) coden können oder?
So hier ist noch mal das gleiche von gestern, das mit dem "T tradeoff" war Schwachsinn, hab ich eingesehen. Außerdem war meine Sortiermethode auch volkommen falsch.
Aber so passt doch die Methode "sort_array" jetzt oder???CODE:
main.cpp
#include <iostream> #include "sort.hpp" int main() { int field[10]={10,2,1,5,4,8,12,11,16,14}; sort<int> grade; grade.sort_array(field,10); for (int i=0;i<10;i++) std::cout << field[i] << std::endl; return 0; }sort.hpp
#ifndef SORT_HPP_INCLUDED #define SORT_HPP_INCLUDED template <class T> class sort { public: sort(); ~sort(); void sort_array(T *array,int length); void swap(T &a,T &b); private: }; template <class T> sort<T>::sort() { } template <class T> sort<T>::~sort() { } template <class T> void sort<T>::sort_array(T *array,int length) { int tradeoff=0; for (int i=0;i<length-1;i++) { tradeoff=i; for (int j=i;j<length;j++) { if (array[tradeoff]>array[j]) { tradeoff=j; } } swap(array[i],array[tradeoff]); } } template <class T> void sort<T>::swap(T &a,T &b) { const T temp=a; a=b; b=temp; } #endif // SORT_HPP_INCLUDEDDankeschön schon mal im Voraus.
-
habe hier jetzt nicht die ganze diskussion mitverfolgt, aber... wozu eigentlich eine klasse ohne member-variablen und ohne gar nichts? wäre hier eine
template<class T> sort(T* pArray, size_t n){...}nicht angemessener?

-
Andrey schrieb:
habe hier jetzt nicht die ganze diskussion mitverfolgt, aber... wozu eigentlich eine klasse ohne member-variablen und ohne gar nichts? wäre hier eine
template<class T> sort(T* pArray, size_t n){...}nicht angemessener?

Wie ich finde, ein sehr guter Vorschlag. Wenn man unbedingt eine Klasse haben möchte, würde ich einen echten "Funktor" bauen:
template <class T> struct sort { void operator()(T *array,size_t length) { size_t tradeoff=0; // wenn size_t gemeint ist, sollte man es auch nehmen for (size_t i=0;i<length-1;i++) { tradeoff=i; for (size_t j=i;j<length;j++) { if (array[tradeoff]>array[j]) tradeoff=j; } // std::swap braucht man nicht nachzuprogrammieren std::swap(array[i],array[tradeoff]); } // Konstruktoren und Destriktoren, die nix tun, braucht keiner };und schon wird auch der Aufruf übersichtlicher:
int main() { int field[10]={10,2,1,5,4,8,12,11,16,14}; sort<int> mySort; mySort(field,10); for (int i=0;i<10;i++) std::cout << field[i] << std::endl; return 0; }Gruß,
Simon2.
-
Ah ja okay, hab das dann so gemacht:
template <class T> void sort<T>::operator() (T *array,int length) { sort_array(array,length); }Was soll den genau ein "Funktor" sein? Is damit sowas gemeint wie ..(int length)... das ding wo man halt argumente reinschreibt?
Dankeschön schon mal im Voraus.
-
Ein Funktor oder Funktionsobjekt ist ein Objekt, das sich wie eine Funktion verhält. Das erreichst du, indem du operator() überlädst.
-
Stromberg schrieb:
...
Was soll den genau ein "Funktor" sein? ..."Funktor" = "Funktionsobjekt" = "Ein Objekt, das eigentlich nur einen Funktionsaufruf darstellt/kapselt".
Sowas wird z.B. in der C++-Standardlib gerne verwendet, weil es letztlich flexibler und syntaktisch einfacher zu handhaben ist als Funktionspointer.Klassischerweise überlädt man den operator(), damit man es einfach aufrufen kann.
Es kann zwar "Status haben" (Attribute, über Konstruktor gesetzt, ...), sollte aber nicht allzuviel innere Logik besitzen und "einfach kopierbar" sein.Ehrlich gesagt: Wenn Du sowieso sort_array() aufrufst, sehe ich überhaupt keinen Nährwert von dem struct mehr.... :p
Gruß,
Simon2.
-
Mh was meinst du mit:
Ehrlich gesagt: Wenn Du sowieso sort_array() aufrufst, sehe ich überhaupt keinen Nährwert von dem struct mehr...
Wo kommt da n struct vor?
Sorry für die blöden Fragen bin halt n Anfänger
Dankeschön schon mal im Voraus.
-
Stromberg schrieb:
Mh was meinst du mit:
Ehrlich gesagt: Wenn Du sowieso sort_array() aufrufst, sehe ich überhaupt keinen Nährwert von dem struct mehr...
Wo kommt da n struct vor?...
(Übrigens: Die Frage finde ich nicht blöd - brauchst Du Dich nicht für entschuldigen)
Hier:
Stromberg schrieb:
... void sort<T>::operator() (T *array,int length) ...Da definierst Du die komplette Funktionalität in eine einzige public Memberfunktion einer Klasse (oder struct). Und diese Klasse beinhaltet selbst keinen "Zustand" oder irgendeine andere Funktionalität.
Mal andersherum gefragt: Warum sollte irgendein User
... sort<int> mySort; // Instantiierung eines Objekts + explizite Typangabe notwendig mySort(array, length); ...aufrufen, wenn er viel einfacher direkt
... // Kein Objekt und keine explizite Typangabe notwendig sort_array(array,length); ...nutzen könnte ?
Natürlich könntest Du ihn dazu zwingen, indem Du sort_array() "versteckst", aber warum ?Gruß,
Simon2.
P.S.: Vielleicht kam Deine Verwirrung auch einfach daher, dass Du "class { public:" geschrieben hast, wo ich lieber "struct {" nehme.
-
Ja gut stimmt, es ist wirklich bisschen kompliziert, und viel Schreibarbeit.
Sollte ich dann vll. einfach eine Template-Funktion verwenden?
Aber weiß nicht ich bin irgendwie grad so "Klassengeil" :D, weil ich denk mir immer das ich ja nicht in "C" bin sondern das ich ja in "C++" bin, und wenn es einem mit den Klassen schon angeboten wird, dann soll man das doch auch machen? Professionelle C++ programmierer machen doch auch alles aus Klassen oder?
Früher vor paar Monaten hab ich immer alles in Funktionen programmiert, aber jetzt will ich irgendwie nur noch Klassen verwenden weil ich glaub des is n besser Programmierstil?
Aber langsam lern ich irgendwie das nicht alles was aus Klassen besteht, zwingend guter Quellcode sein muss.
Äh und dann hab ich noch folgendes ausprobieren wollen, aber es hat irgendwie nicht richtig funktioniert. Ich wollte in "sort.hpp" ein Klassenobjekt erstellen (also extern), sodass man das dann immer ganz einfach in der "main.cpp" aufrufen kann, ohne extra ein neues Objekt zu erstellen.
Das wäre doch schon ein bisschen benutzerfreundlicher oder?main.cpp
#include <iostream> #include "sort.hpp" int main() { int buffer; int field[10]; for (int i=0;i<10;i++) { std::cin >> buffer; field[i]=buffer; } std::cout << "\n"; sorting(field,10); for (int i=0;i<10;i++) { std::cout << field[i] << "\n"; } return 0; }sort.hpp
#ifndef SORT_HPP_INCLUDED #define SORT_HPP_INCLUDED template <class T> class sort { public: sort(); ~sort(); void sort_array(T *array,int length); void swap(T &a,T &b); void operator() (T *array,int length); private: }; template <class T> sort<T>::sort() { } template <class T> sort<T>::~sort() { } template <class T> void sort<T>::sort_array(T *array,int length) { int tradeoff=0; for (int i=0;i<length-1;i++) { tradeoff=i; for (int j=i;j<length;j++) { if (array[tradeoff]>array[j]) { tradeoff=j; } } swap(array[i],array[tradeoff]); } } template <class T> void sort<T>::swap(T &a,T &b) { const T temp=a; a=b; b=temp; } template <class T> void sort<T>::operator() (T *array,int length) { sort_array(array,length); } extern sort<int> sorting; #endif // SORT_HPP_INCLUDEDERROR:
-------------- Build: Debug in sortieren ---------------
Compiling: main.cpp
Linking console executable: .\sortieren.exe
obj\Debug\main.o: In functionmain': C:/MinGW/Andi/C++/Projekte/sortieren/main.cpp:14: undefined reference tosorting'
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
1 errors, 0 warningsDankeschön schon mal im Voraus.
-
Kurze Antwort: Lass die Klasse weg und schreib eine einfache (Template-)Funktion zur Sortierung. Wie Simon schon gesagt hat, ist die Klasse an dieser Stelle nur eine unnütze Spielerei.
-
Stromberg schrieb:
Ja gut stimmt, es ist wirklich bisschen kompliziert, und viel Schreibarbeit.
Sollte ich dann vll. einfach eine Template-Funktion verwenden? ...Japp !
Sortieren ist einfach ein ganz klassischer Algorithmus ... und hat von der Aufgabenstellung nichts "Objektartiges". Deswegen würde ich auch nicht versuchen, es als Klasse zu modellieren.@"C++ machen": Machst Du doch ! Generische Programmierung mit templates ist absolutes C++.

Wenn Du "Klassenübungen" machen möchtest, solltest Du Dir eine andere Aufgae suchen.
Gruß,
Simon2.