Hilfe bei Klassendefinition
-
Hallo zusammen,
taste mich gerade an die Klassenprogrammierung unter C++ heran, komme aber irgendwie nicht weiter.
Vielleicht kann mir jemand folgendes Problem lösen, damit ich es als Anschauungsbeispiel nehmen kann.
Ich möchte eine Klasse matrix erstellen und auf folgende Art und Weise aufrufbar sein:
Beispiel:
matrix A(4,4) bzw. matrix A(5);
Dabei soll dann ein Array der Größe 4*4 bzw. 5*1 erstellt werden und auf den Namen A abgespeichert werden. Zudem soll die Klasse eine Funktion zur Sortierung enthalten, eine Funktion um das (Minimum bzw. das Maximum | Spaltenweise) zu finden.
Ich möchte nicht, dass ich eine komplette Lösung bekomme, sondern nur in etwa den Aufbau der Klasse. Verstehe nicht so richtig wie die Übergabe der Variablen etc. funktioniert. Das schreiben der Funktionen ist kein Problem. Das wäre schon eine große Hilfe...
Vielen Dank und Liebe Grüße
Theo
-
Nja ... also von welchem Typ soll der Array denn sein? Oder willst du mit Templates arbeiten?
Zu deinem Beispiel ... mach halt einen Konstruktor der die beiden Dimensionen haben will und geb beiden einen Defaultwert(1).
Max&Min: http://www.cppreference.com/cppalgorithm/max_element.html bzw http://www.cppreference.com/cppalgorithm/min_element.html
Sortieren ... welchen Algorithmus hättest de denn gerne? BubbleSort, QuickSort usw ... guck dich halt etwas um

-
Danke für deine Antwort,
aber wie gesagt die Programmierung ist kein Ding, mir geht es ausschließlich darum, dass ich die ganze Klassenthematik nicht so ganz verstehe...
Viele Fehler aber so in etwa...
class matrix { char* s; double minimum,maximum; public: double min(); double max(); double quicksort(); matrix(const int* anzzeilen,const int* anzspalten) {???=new double[anzzeilen][anzspalten]; return ???;}; matrix(const int* anzzeilen) {???=new double[anzzeilen]; return ???;}; }; double matrix::min() { ... return 'minimum'; } double matrix::max() { ... return 'maximum'; } double quicksort() { ... return 'sortiertesarray' }Wahrscheinlich ist das völliger Schrott was hier steht.
Mir geht es nur darum, wie ich definieren kann, dass die Klasse "matrix" folgendermaßen aufgerufen werden kann:
matrix A(4)...Es ein Array erstellt der Dimension 4x1 mit dem Namen 'A' usw...
Wie kann ich dann z.B. A[0] einen Wert zuweisen?
A.min bzw. A.max sollen das Minimum über dem ganzen Array bzw. das Maximum zurückgeben.
A.quicksort() soll das Array sortieren. Wie übergebe ich denn, wenn ich A.quicksort() aufrufe das Array 'A' das zu sortieren ist.Das genau sind meine Probleme...Heiei...der Klassenaufbau
Liebe Grüße
Theo
-
Erstmal sortiere ich die Klasse ein wenig, nur damit ich durchblicke...

class matrix { char* s; double minimum,maximum; public: double min(); double max(); double quicksort(); matrix( int anzzeilen, int anzspalten) { ???=new double[anzzeilen][anzspalten]; return ???; } matrix( int anzzeilen ) { ???=new double[anzzeilen]; return ???;}; } };matrix A(4)
Das ist ziemlich einfach. Du sagst mit der Zeile ja, dass du ein Objekt vom Typ "Matrix" willst. Zusätzlich übergibst du der Matrix noch einen Start-Wert, hier die '4'.
Die Startwerte bekommst du, wie du's ja schon hast, im Konstruktor der Klasse. Wieso du da aber Zeiger auf einen Zahlenwert übergeben willst, ist mir schleierhaft. Wie dem auch sei, das "const int*" aus dem Konstruktor kannst du getrost durch "int" austauschen, schließlich willst du keinen Zeiger auf eine Zahl, die du nicht verändern darfst, sondern einfach nur eine Zahl
Für den Rest lege ich dir der Einfachheit halber (will mir keinen Wolf schreiben ;)) mal Google mit dem Stichwort "C++ Tutorial" ans Herz. Dir fehlen ganz einfach die Grundlagen, welche du (meiner Meinung nach) vor dem Klassen-Konzept lernen solltest. Du solltest zumindest wissen, was ein Zeiger ist, was Zeichenketten sind usw.
Lass dich aber nicht entmutigen, es kommt der Tag an dem dein erster selbstgeschriebener Source kompiliert!
-
template <typename T> class matrix { public: matrix(std::size_t row = 1, std::size_t col = 1) : m_row(row), m_col(col) { m_data = new T*[row]; for (std::size_t cur = 0; cur < row; ++cur) m_data[cur] = new T[col]; } ~matrix() { for (std::size_t cur = 0; cur < m_row; ++cur) delete [] m_data[cur]; delete [] m_data; } public: T const & at(std::size_t row, std::size_t col) const { if (row > m_row || col > m_col) throw std::out_of_range("col or row"); return m_data[row][col]; } T const & min() const { T const & min; for (std::size_t row = 0; row < m_row; ++row) for (std::size_t col = 0; col < m_col; ++col) min = std::min(m_data[row][col], min); return min; } T const & max() const { T const & max; for (std::size_t row = 0; row < m_row; ++row) for (std::size_t col = 0; col < m_col; ++col) max = std::max(m_data[row][col], max); return max; } private: T** m_data; std::size_t m_row; std::size_t m_col; };...
sind nen paar const usw. zu viel drin und kann sein das ich col und row vertauscht hab
an sonnsten ... so wird's gemacht 
-
Bleibt nur eine Frage: Warum nicht template<typename T,size_t rows,size_t cols>?

Ansonsten schöne Klasse und ich denke Theodor wird sie auf Anhieb verstehen
Und noch eine Frage meinerseits: Macht es eigentlich einen Unterschied ob man template<typename T> oder template<class T> verwendet?
-
template <typename T> oder template <class T> macht keinen Unterschied. Das konstrukt mit typename(im gegensatz zu class) suggeriert dem Benutzer, dass auch primitive datentypen benutzt werden können.
-
Badestrand schrieb:
Bleibt nur eine Frage: Warum nicht template<typename T,size_t rows,size_t cols>? ...
Kommt drauf an, was man will: Mit rows/cols als template-Parameter kann man direkt ein statisches Array verwenden ... aber die Größe eben auch nicht mehr zur Laufzeit ändern.
Außerdem haben unterschiedlich dimensionierte Matrizen dann auch unterschiedliche (= inkompatible) Typen ... kann gewollt sein, muss aber nicht.Gruß,
Simon2.
-
megaweber schrieb:
template <typename T> oder template <class T> macht keinen Unterschied. Das konstrukt mit typename(im gegensatz zu class) suggeriert dem Benutzer, dass auch primitive datentypen benutzt werden können.
ich sehs eigentlich genau andersrum: "class" suggeriert, dass auch klassen verwendet dürfen. im gegensatz zu typename, welches andeutet, dass die methode für primitive typen gedacht ist.
-
thordk schrieb:
ich sehs eigentlich genau andersrum: "class" suggeriert, dass auch klassen verwendet dürfen. im gegensatz zu typename, welches andeutet, dass die methode für primitive typen gedacht ist.
Dies ist aber eine unübliche Betrachtungsweise (zumal typename auch an anderen Stellen als im Templatekopf verwendet wird, und es dort auch Klassen als Möglichkeit gibt).
Um grade Anfänger nicht durcheinander zu bringen wäre es besser sich an die Definitionen anzulehnen, die man auch so in vielen Fachbüchern findet:
class : Nur Klassentypen
typename : Klassentypen + primitive Typencu André
-
Hmm ... ich wusste doch das zu viele const in der Klasse sind ... also bei at müssen 2 raus
Sonnst kannst du die werte nie ändern 
namespace math { template <typename T> class matrix { public: matrix(std::size_t row = 1, std::size_t col = 1) : m_row(row), m_col(col) { m_data = new T*[row]; for (std::size_t cur = 0; cur < row; ++cur) m_data[cur] = new T[col]; } ~matrix() { for (std::size_t cur = 0; cur < m_row; ++cur) delete [] m_data[cur]; delete [] m_data; } public: T& at(std::size_t row, std::size_t col) { if (row > m_row || col > m_col) throw std::out_of_range("col or row"); return m_data[row][col]; } T const & min() const { T const & min; for (std::size_t row = 0; row < m_row; ++row) for (std::size_t col = 0; col < m_col; ++col) min = std::min(m_data[row][col], min); return min; } T const & max() const { T const & max; for (std::size_t row = 0; row < m_row; ++row) for (std::size_t col = 0; col < m_col; ++col) max = std::max(m_data[row][col], max); return max; } std::size_t size() const { return (m_row * m_col); } private: T** m_data; std::size_t m_row; std::size_t m_col; }; }; int main() { math::matrix<double> mat(4, 4); mat.at(1, 1) = mat.size(); }
so bin ich zufrieden ... hatte auch an ne clear-Methode gedacht ... aber ich kann ja nicht davon ausgehen das ich einer normalen Klasse 0 zuweisen kann
Könnte aber auch hingehen und alles einmal löschen und dann neu anlegen ... also man kann nochn paar sachen implementieren ...Aja zur Suche: Wie willst de es denn sortiert haben? Soll jede Zeile für sich sortiert sein oder alles zusammen?(was nicht geht ...)
-
So ... jetzt können wir auch noch resizen ... und zu beachten: operator () wirft natürlich keine exception ... at aber schon ... so wie std::vector udg. auch.
#include <algorithm> namespace math { template <typename T> class matrix { public: matrix(std::size_t row = 1, std::size_t col = 1) : m_row(row), m_col(col) { m_data = new T*[row]; for (std::size_t cur = 0; cur < row; ++cur) m_data[cur] = new T[col]; } ~matrix() { for (std::size_t cur = 0; cur < m_row; ++cur) delete [] m_data[cur]; delete [] m_data; } T& operator ()(std::size_t row, std::size_t col) { return m_data[row][col]; } public: T& at(std::size_t row, std::size_t col) { if (row > m_row || col > m_col) throw std::out_of_range("col or row"); return m_data[row][col]; } T const & min() const { T const & min; for (std::size_t row = 0; row < m_row; ++row) for (std::size_t col = 0; col < m_col; ++col) min = std::min(m_data[row][col], min); return min; } T const & max() const { T const & max; for (std::size_t row = 0; row < m_row; ++row) for (std::size_t col = 0; col < m_col; ++col) max = std::max(m_data[row][col], max); return max; } std::size_t size() const { return (m_row * m_col); } void resize(std::size_t row, std::size_t col) { T** tmp_data = new T*[row]; for (std::size_t cur_row = 0; cur_row < row; ++cur_row) { tmp_data[cur_row] = new T[col]; for (std::size_t cur_col = 0; cur_col < col; ++cur_col) if (cur_col < m_col && m_row > cur_row) tmp_data[cur_row][cur_col] = m_data[cur_row][cur_col]; } for (std::size_t cur = 0; cur < m_row; ++cur) delete [] m_data[cur]; delete [] m_data; m_data = tmp_data; m_row = row; m_col = col; } private: T** m_data; std::size_t m_row; std::size_t m_col; }; }; double test() { math::matrix<double> mat(4, 4); mat.at(1, 1) = mat.size(); mat.resize(6,6); mat(5, 1) = 1; return mat.at(5, 1); }...
-
aja ... wer auf die Standardbibliothek verzichten will ... muss nur kurz
namespace math { template <typename T> T& min(T const& a, T const& b) { return (a > b ? b : a); } template <typename T> T& max(T const& a, T const& b) { return (a > b ? a : b); } };am Anfang schreiben und aus std::max bzw std::min einfach math::min bzw math::max machen

-
Hier noch was

namespace math { template <typename T> void bubble_sort(T*& arr, std::size_t size) { bool redo = false; do { redo = false; for (std::size_t i = 0; (i < (size - 1) && arr[i] != NULL && arr[i+1] != NULL); ++i) if (arr[i] > arr[i + 1]) { std::swap<T>(arr[i], arr[i + 1]); redo = true; } } while (redo == true); } };=>
class matrix { // ... void sort() { for (std::size_t cur_row = 0; cur_row < m_row; ++cur_row) bubble_sort<T>(m_data[cur_row], m_col); } // ... };
-
(D)Evil schrieb:
So ... jetzt können wir auch noch resizen ... und zu beachten: operator () wirft natürlich keine exception ... at aber schon ... so wie std::vector udg. auch.
Jetzt hast du dich ja richtig ausgetobt. Ich finde die Klasse gut, aber wieso wirft der operator() keine exception? Das macht aus meiner Sicht keinen Sinn.
-
hmm ... nja wollte eigentlich nen [][] operator implementieren ... aber das ist ja nicht so ohne weiteres möglich ... deswegen hab ich dne operator () genommen ...[] wirft auch keine exceptions in der std. lib
nja ist eigentlich nicht sooo sinvoll
aber egal ... mir ist gerade auch eingefallen das der operator [][] garnicht sooo das problem wäre ... aber egal ^^