Matrix-Klasse | dyn Array in Klasse
-
Kurze Frage:
Ich möchte mir ne Matrix Klasse bauen... Die sieht so aus...
class matrix { public: matrix(int Zeile, int Spalte); ~matrix(); double get(int Zeile, int Spalte); void set(int Zeile, int Spalte, double Value); int getRang(); int size(); void output_Matrix(); private: int Zeile_; int Spalte_; int Rang; double *Speicher; };Diese Matrix soll eine dynamische Größe haben. Also Zeile * Spalte.
Das alles tu ich in nem Vektor abspeichern. Da ich ja in der Klassendeklaration nicht double Speicher[Zeile*Spalte] schreiben kann (habs probiert) hab ich nen Pointer gemacht.Im Konstruktor erstell ich mir dann dyn. ein Array. Mein Pointer zeigt dann auf dieses Array
So halt:
matrix::matrix(int Zeile, int Spalte) { double *SP = new double(Zeile*Spalte); this->S = SP; // bla bla bla for (int i=0; i< Zeile*Spalte; i++) S[i] = 0; }Frage 1: Ist das so geschickt?
Frage 2: Wie tu ich dann dieses dyn Array wieder löschen?vielen Dank soweit
Cascoin
-
casicas13 schrieb:
Diese Matrix soll eine dynamische Größe haben. Also Zeile * Spalte.
Das alles tu ich in nem Vektor abspeichern. Da ich ja in der Klassendeklaration nicht double Speicher[Zeile*Spalte] schreiben kann (habs probiert) hab ich nen Pointer gemacht.So nah und doch so fern. Hättest du vector statt Vektor geschrieben, hättest du die perfekte Lösung.
Frage 1: Ist das so geschickt?
Jain. An sich eine gute Idee, aber du erfindest gerade die Standardbibliothek neu.
Frage 2: Wie tu ich dann dieses dyn Array wieder löschen?
Im Destruktor. Google mal RAII.
-
casicas13 schrieb:
Frage 1: Ist das so geschickt?
Frage 2: Wie tu ich dann dieses dyn Array wieder löschen?Zu 1:
Nein. Als Übung zum Thema Resourcenverwaltung, ja. Du erfindest aber das Rad "vector" neu. Das ist natürlich nicht nötig.Zu 2:
Überlässt du die Verwaltung einer Resource (wie reserviertern Speicher) einem Objekt (was immer eine gute Idee ist), solltst Du der Klasse einen selbstgeschriebenen Destruktor spendieren, der diese Resource wieder freigibt und auch darauf achten, dass Kopieroperationen, die der Compiler gerne selbst erzeugt, auch das richtige Verhalten haben oder eben explizit deaktiviert werden. Mit Kopieroperationen meine ich den Kopierkonstruktor und den Zuweisungsoperator. Stichwort: Dreierregel.Wenn Du stattdessen einfach std::vector verwendest, musst Du Dich um die Verwaltung des dynamisch reservierten Speichers gar nicht kümmern. Das macht std::vector ja schon:
#include <cassert> #include <vector> class matrix { public: matrix() : zeilen_(0), spalten_(0) {} matrix(int Zeilen, int Spalten) { resize(Zeilen,Spalten); } void resize(int Zeilen, int Spalten); int zeilen() const {return zeilen_;} int spalten() const {return spalten_;} double operator()(int i, int j) const {return elemente_[index_von(i,j)];} double& operator()(int i, int j) {return elemente_[index_von(i,j)];} private: typedef std::vector<double>::size_type size_type; size_type index_von(int i, int j) const { assert(0<=i && i<zeilen_); assert(0<=j && j<spalten_); return size_type(i)*spalten_ + j; } int zeilen_; int spalten_; std::vector<double> elemente_; }; //--- noch zu implementieren in einer cpp-datei: void matrix::resize(int Zeilen, int Spalten) { elemente_.resize(size_type(Zeilen)*size_type(Spalten)); }Ein Matrix-Objekt ist damit ganz automatisch kopier- und zuweisbar, ohne dass da viel schief gehen kann. Die Vom Compiler erzeugten Operationen kopieren elementweise, also zwei ints und einen vector.
Edit: const bei index_von vergessen.
-
Ze fix,
Ich dank euch beiden.... Jetzt hab ichs grad (fast) so gemacht wie "krümelkacker". Nur halt ohne die Operatoren...
Aber ich glaub ich übernehm einfach deins...
Danke!
Cascoin
-
Wenn
zeilenundspaltenjetzt noch vom Typstd::size_tstattintwären würde ich vorschlagen, das in die FAQ aufzunehmen (vielleicht sogar noch als templated Version). Die Frage nach irgendwelchen 2D Arrays taucht hier im Forum doch ziemlich häufig auf, und meistens wird eine Lösung vorgestellt, die der hier sehr ähnlich ist.
-
Jetzt hab ich doch noch was:
Also ich habs jetzt genau so bei mir reinkopiert...Leider funktioniert des nicht.
Der hat mit den Operatoren ein Problem.Hier mal die Fehlermeldung:
error:passing ‘const matrix2’ as ‘this’ argument of ‘size_t matrix2::index_von(int, int)’ discards qualifiers(Ich versteh leider nicht warum ihm das nicht gefällt....
-
Mach die
index_vonMethodeconst.Edit:
Und wenn du das so einsetzen willst solltest du den Code in Header- und Implementationsdatei aufteilen.
-
Du hast irgendwo ein konstante Matrix. Für diese Matrix kannst du nur konstante Methoden aufrufen - das sind Methoden, die den Zustand des Objektes nicht ändern (ja, ich weiß, es gibt "mutable"...).
-
DocShoe schrieb:
Mach die
index_vonMethodeconst.
Flüchtigkeitsfehler meinerseits.Also, von wegen FAQ Eintrag: Sicherlich ist das mal interessant, so ein Codebeispiel zu sehen. Aber vorgefertigt und noch einen Tucken flexibler gibt es da ja auch schon: boost::multi_array
-
krümelkacker schrieb:
Also, von wegen FAQ Eintrag: Sicherlich ist das mal interessant, so ein Codebeispiel zu sehen. Aber vorgefertigt und noch einen Tucken flexibler gibt es da ja auch schon: boost::multi_array
Leuten, die boost installieren und benutzen, traue ich auch zu, dass sie ein 2D Arrayklasse programmieren können. Oft fragen aber Anfänger, die sich erst seit kurzem mit C++ beschäftigen (z.B. im Rahmen einer Hausaufgabe/Semesterarbeit), und die benutzen so gut wie nie boost.