mars12 Geschrieben 5. Dezember 2008 Teilen Geschrieben 5. Dezember 2008 Habe eine Klasse Matrix geschrieben, die folgendermaßen aussieht: class CZeile { protected: [INDENT]double *z; int size; [/INDENT] public: [INDENT]~CZeile(void) {delete [] this->z}; CZeile(int s){this->size = s; this->z = new double[s];} [/INDENT] } class CMatrix:public CZeile { protected: [INDENT]CZeile **mat; //Zeiger auf "Zeilen"-Vektor int lines, cols; //Zeilen- und Spaltenzahl [/INDENT] public: [INDENT]~CMatrix(void) { [INDENT]for (int i = 0; i < this->lines; i++) { [INDENT][/INDENT] [INDENT]delete this->mat[i]; [/INDENT] } [/INDENT] [INDENT][/INDENT][INDENT]delete[] this->mat; [/INDENT] } [/INDENT] [INDENT]CMatrix(int z, int s, double wert) { [INDENT]this->lines = z; this->cols = s; this->mat = new CZeile*[this->lines]; //Vektor fuer Zeiger auf Zeilenvektoren int i, j; for (i = 0; i < this->lines; i++) //Zeilenvektoren: { [INDENT]this->mat[i] = new CZeile(this->cols); //Speicher reservieren [/INDENT] [INDENT]for (j = 0; j < this->cols; ++j) { [INDENT](*this)[i][j] = wert; //und Werte kopieren [/INDENT] }[/INDENT]}[/INDENT] } [/INDENT]} Soweit so gut, Matrix anlegen und damit arbeiten funktioniert alles, aber wenn ich im Debugmodus das Programm beenden möchte und den Destruktor aufrufe, kommt folgende Fehlermeldung: Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffff9. Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffff9. Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffffa. Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffffa. Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffffb. Eine Ausnahme (erste Chance) bei 0x7c97d811 in test21.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0xfffffffb. HEAP[test21.exe]: Invalid Address specified to RtlFreeHeap( 00030000, 7C958FB7 ) Unbehandelte Ausnahme bei 0x7c91120e in test21.exe: Benutzerhaltepunkt. Das Programm "[2496] test21.exe: Systemeigen" wurde mit Code 0 (0x0) beendet. Habe schon herausgefunden, dass die Adresse 7C958FB7 das Element mat (also bei delete[] this->mat) ist. Dann wird der Destruktor von CZeile aufgerufen und es knallt. Programmier noch nicht so lang, vielleicht kann mir das jemand erklären? Versteh soweit schon, dass ich auf Speicher zugreife, den es offensichtlich nicht mehr gibt, aber wo in meinem Code soll der Fehler liegen? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Guybrush Threepwood Geschrieben 5. Dezember 2008 Teilen Geschrieben 5. Dezember 2008 Also das sieht doch alles sehr komisch aus. Warum leitest du CMatrix von CZeile ab? Warum ist mat ein CZeile**? So wie ich das sehe willst du ein CZeile*, das andere würde dir nur was bringen wenn du statt this->mat[i] = new CZeile(this->cols); [/PHP] sowas [PHP] this->mat[i] = new CZeile[15]; machen würdest und damit im Prinzip ein dreidimensionales Array aus double Werten schaffen würdest. Das hier (*this)[i][j] = wert; //und Werte kopieren [/PHP] ist mir auch nicht so ganz geheuer und ich würde nicht vermuten das das definiertes Verhalten versucht, aber auf alle Fälle ist es nicht schön. Wozu brauchst du eigentlich CZeile und machst nicht einfach ein double** in CMatrix? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 5. Dezember 2008 Teilen Geschrieben 5. Dezember 2008 Der Code lässt sich so überhaupt nicht kompilieren. Erstens hat CZeile keinen Defaultkonstruktor, und zweitens hat weder CMatrix noch CZeile einen operator[]. Da sind noch andere Fehler drin, die nahelegen, dass mars12 hier versucht hat, "Beispielcode" zu zeigen. Das eigentliche Problem vermute ich darin, dass hier vergessen wurde, die Regel der großen Drei zu befolgen: Wenn eine Klasse eines dieser drei hat: - Nichttrivialer Destruktor - Copykonstruktor - Copy-Zuweisungsoperator Dann braucht sie alle drei. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
mars12 Geschrieben 8. Dezember 2008 Autor Teilen Geschrieben 8. Dezember 2008 OK, hatte nicht meinen kompletten Code geschrieben, da ich dachte das sprengt den Rahmen. Hier noch einmal: class CZeile { protected: double *z; //Zeiger auf Zeile int size; //Groesse der Zeile public: CZeile(void); //Konstruktor virtual ~CZeile(void); //Destruktor CZeile(int s); //parametrisierter Konstruktor double& operator[](int i); //prueft den Indexwert auf Gueltigkeit const double& operator [](int i) const; //prueft den Indexwert auf Gueltigkeit virtual void print(void); //Bildschirmausgabe }; CZeile::CZeile(void) { } CZeile::~CZeile(void) { delete [] this->z; } CZeile::CZeile(int s) { this->size = s; this->z = new double[s]; } double& CZeile::operator[](int i) { if (i < 0 || i > this->size) { throw out_of_range("Spaltenindex: Out of Range\n"); } return this->z[i]; } const double& CZeile::operator [](int i) const { if (i < 0 || i > this->size) { throw out_of_range("Spaltenindex: Out of Range\n"); } return this->z[i]; } void CZeile::print(void) //Bildschirmausgabe { } class CMatrix : public CZeile { protected: CZeile **mat; //Zeiger auf "Zeilen"-Vektor int lines, cols; //Zeilen- und Spaltenzahl long int itsSum; //Summe public: CMatrix(void); //Konstruktor ~CMatrix(void); //Destruktor CMatrix(int z, int s, double wert); //parametrisierter Konstruktor CMatrix(int z, int s); //parametrisierter Konstruktor int getLines(void);//gibt die Zeilenanzahl zurueck int getCols(void); //gibt die Spaltenanzahl zurueck const CZeile& operator[] (int i) const;//prueft den Indexwert auf Gueltigkeit CZeile& operator[](int i);//prueft den Indexwert auf Gueltigkeit CMatrix& operator=(const CMatrix&); //Einfache Zuweisung CMatrix& operator+=(const CMatrix&);//Addition zweier Matrizen und Zuweisung virtual void print(); //Bildschirmausgabe void setWert(int z, int s, double WertTmp);//traegt Wert an bestimmte Stelle in Matrix ein long int sum(void); //bildet Summe der Matrix double getWert(int z, int s); //gibt Wert an bestimmter Stelle in Matrix zurueck CMatrix(const CMatrix& m);//Copy-Konstruktor }; CMatrix::CMatrix(void) { } CMatrix::~CMatrix(void) { for (int i = 0; i < this->lines; i++) { delete this->mat[i]; } delete[] this->mat; } CMatrix::CMatrix(int z, int s, double wert) { this->lines = z; this->cols = s; this->mat = new CZeile*[this->lines]; //Vektor fuer Zeiger auf Zeilenvektoren int i, j; for (i = 0; i < this->lines; i++) //Zeilenvektoren: { this->mat[i] = new CZeile(this->cols); //Speicher reservieren for (j = 0; j < this->cols; ++j) { (*this)[i][j] = wert; //und Werte kopieren } } } CMatrix::CMatrix(int z, int s) { this->lines = z; this->cols = s; this->mat = new CZeile*[this->lines]; for (int i = 0; i < this->lines; i++) { this->mat[i] = new CZeile(this->cols); } } int CMatrix::getLines(void) { return this->lines; } int CMatrix::getCols(void) { return this->cols; } CZeile& CMatrix::operator[](int i) { if(i < 0 || i > this->lines) { throw out_of_range("Zeilenindex: Out of Range\n"); } return *mat[i]; } const CZeile& CMatrix::operator[](int i) const { if(i < 0 || i > this->lines) { throw out_of_range("Zeilenindex: Out of Range\n"); } return *mat[i]; } CMatrix& CMatrix::operator=(const CMatrix& m) { int i, j; //Alten Speicher freigeben for (i = 0; i < this->lines; i++) { delete[] this->mat[i]; } delete[] this->mat; this->lines = m.lines; //Zeilen this->cols = m.cols; //Spalten this->mat = new CZeile*[this->lines]; //Vektor fuer Zeilenvektoren for (i = 0; i < this->lines; ++i) //Zeilenvektoren { this->mat[i] = new CZeile(this->cols); //Speicher reservieren for (j = 0; j < this->cols; ++j) { (*this)[i][j] = m[i][j]; //Werte kopieren } } return *this; } CMatrix& CMatrix::operator+=(const CMatrix& m) { int i, j; if (this->cols == m.cols && this->lines == m.lines) { for (i = 0; i < this->lines; ++i) { for (j = 0; j < this->cols; ++j) { (*this)[i][j] += m[i][j]; } } } return *this; } void CMatrix::print() //Bildschirmausgabe { for (int i = 0; i < this->lines; i++) { for (int j = 0; j < this->cols; ++j) { cout << (*this)[i][j] << " "; } cout << endl; } } void CMatrix::setWert(int z, int s, double WertTmp) { (*this)[z][s] = WertTmp; //und Werte kopieren } long int CMatrix::sum(void) { this->itsSum = 0; //Wert zurueck setzen int i, j; for (i = 0; i < this->lines; i++) { for (j = 0; j < this->cols; ++j) { this->itsSum = this->itsSum + (*this)[i][j]; } } return this->itsSum; } double CMatrix::getWert(int z, int s) { return (*this)[z][s]; } CMatrix::CMatrix(const CMatrix& m) { int i, j; this->lines = m.lines; //Zeilen this->cols = m.cols; //Spalten this->mat = new CZeile*[this->lines]; //Vektor fuer Zeilenvektoren for (i = 0; i < this->lines; ++i) //Zeilenvektoren { this->mat[i] = new CZeile(this->cols); //Speicher reservieren for (j = 0; j < this->cols; ++j) { (*this)[i][j] = m[i][j]; //Werte kopieren } } } [/PHP] Die "grossen Drei" sind doch richtig implementiert, oder nicht? Programmier noch nicht so lange und finde das mit den Zeigern auf Zeiger schon ziemlich tricky. Irgendeiner zeigt ins Nirvana. Wäre dankbar, wenn mir jemand helfen könnte. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 8. Dezember 2008 Teilen Geschrieben 8. Dezember 2008 Das Problem ist, was Guybrush Threepwood bereits erwähnt hat. CMatrix erbt von CZeile, was totaler Blödsinn ist. Damit enthält jedes CMatrix-Objekt ein CZeile-Objekt. Da CZeile aber keinen sauberen Default-Konstruktor hat, bleibt der z-Member dieses Objekts uninitialisiert. Und wenn ein CMatrix-Objekt zerstört wird, wird auch der Basisklassendestruktor ausgeführt. Der ruft dann delete auf einen unitialisierten Zeiger auf -> Peng. Übrigens, CZeile braucht auch Copykonstruktor und Copy-Zuweisungsoperator. Und überhaupt wäre das ganze mit std::vector viel, viel einfacher. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
mars12 Geschrieben 8. Dezember 2008 Autor Teilen Geschrieben 8. Dezember 2008 Verstehe. Habe jetzt mal versucht das ohne CZeile und mit double ** zu implementieren, aber wie Du schon sagtest, ist das auch nicht so ganz einfach. Jetzt funktioniert nämlich mein operator [] nicht mehr. Wie könnte das denn mit vectoren aussehen? Ich nehme an, dass ich dann keine Operatoren mehr Überladen muss? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 8. Dezember 2008 Teilen Geschrieben 8. Dezember 2008 Wie könnte das denn mit vectoren aussehen? Ich nehme an, dass ich dann keine Operatoren mehr Überladen muss? Doch, du musst immer noch den operator[] implementieren, weil du von std::vector nicht erben sollst. Das könnte so aussehen: class CMatrix { private: vector<vector<double> > mat; public: CMatrix(int z, int s, double wert); //parametrisierter Konstruktor CMatrix(int z, int s); //parametrisierter Konstruktor int getLines(void) const;//gibt die Zeilenanzahl zurueck int getCols(void) const; //gibt die Spaltenanzahl zurueck const vector<double>& operator[] (int i) const;//prueft den Indexwert auf Gueltigkeit vector<double>& operator[](int i);//prueft den Indexwert auf Gueltigkeit CMatrix& operator+=(const CMatrix&);//Addition zweier Matrizen und Zuweisung void print() const; //Bildschirmausgabe void setWert(int z, int s, double WertTmp);//traegt Wert an bestimmte Stelle in Matrix ein double sum(void) const; //bildet Summe der Matrix double getWert(int z, int s) const; //gibt Wert an bestimmter Stelle in Matrix zurueck }; CMatrix::CMatrix(int z, int s, double wert) : mat( z, vector<double>( s, wert ) ) { } CMatrix::CMatrix(int z, int s) : mat( z, vector<double>( s ) ) { } int CMatrix::getLines(void) const { return mat.size(); } int CMatrix::getCols(void) const { return mat[0].size(); } vector<double>& CMatrix::operator[](int i) { return mat.at(i); } const vector<double>& CMatrix::operator[](int i) const { return mat.at(i); } CMatrix& CMatrix::operator+=(const CMatrix& m) { if (getCols() == m.getCols() && getLines() == m.getLines() ) { for (int i = 0; i < getLines(); ++i) { for (int j = 0; j < getCols(); ++j) { mat[i][j] += m.mat[i][j]; } } } return *this; } void CMatrix::print() const //Bildschirmausgabe { for (int i = 0; i < getLines(); i++) { for (int j = 0; j < getCols(); ++j) { cout << mat[i][j] << " "; } cout << endl; } } void CMatrix::setWert(int z, int s, double WertTmp) { mat[z][s] = WertTmp; //und Werte kopieren } double CMatrix::sum(void) const { double sum = 0.0; //Wert zurueck setzen for(size_t i = 0; i < mat.size(); i++) { sum = accumulate( mat[i].begin(), mat[i].end(), sum ); } return sum; } double CMatrix::getWert(int z, int s) const { return mat[z][s]; }[/code] Für accumulate brauchst du <numeric>. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
mars12 Geschrieben 8. Dezember 2008 Autor Teilen Geschrieben 8. Dezember 2008 Hmmm... Das ist ganz neu für mich. Hab das jetzt mal folgendermaßen implementiert: #pragma once #include <numeric> class CMatrix { protected: vector<vector<double> > mat; public: CMatrix(int z, int s, double wert); //parametrisierter Konstruktor //CMatrix(int z, int s); //parametrisierter Konstruktor int getLines(void) const;//gibt die Zeilenanzahl zurueck int getCols(void) const; //gibt die Spaltenanzahl zurueck const vector<double>& operator[] (int i) const;//prueft den Indexwert auf Gueltigkeit vector<double>& operator[](int i);//prueft den Indexwert auf Gueltigkeit CMatrix& operator+=(const CMatrix&);//Addition zweier Matrizen und Zuweisung void print() const; //Bildschirmausgabe void setWert(int z, int s, double WertTmp);//traegt Wert an bestimmte Stelle in Matrix ein double sum(void) const; //bildet Summe der Matrix double getWert(int z, int s) const; //gibt Wert an bestimmter Stelle in Matrix zurueck CMatrix(void); //Konstruktor ~CMatrix(void); //Destruktor CMatrix& operator=(const CMatrix&); //Einfache Zuweisung }; #include "StdAfx.h" #include ".\matrix.h" #include <numeric> CMatrix::CMatrix(void) :mat(NULL) { } CMatrix::~CMatrix(void) { } CMatrix::CMatrix(int z, int s, double wert) : mat( z, vector<double>( s, wert ) ) { for (int i = 0; i < getLines(); i++) //Zeilenvektoren: { for (int j = 0; j < getCols(); ++j) { mat[i][j] = wert; //und Werte kopieren } } } /*CMatrix::CMatrix(int z, int s) : mat( z, vector<double>( s ) ) { this->lines = z; this->cols = s; this->mat = new vector<double>[this->lines]; for (int i = 0; i < this->lines; i++) { this->mat[i] = new double(this->cols); } }*/ int CMatrix::getLines(void) const { return mat.size(); } int CMatrix::getCols(void) const { return mat[0].size(); } vector<double>& CMatrix::operator[](int i) { return mat.at(i); } const vector<double>& CMatrix::operator[](int i) const { return mat.at(i); } CMatrix& CMatrix::operator=(const CMatrix& m) { for (int i = 0; i < getLines(); ++i) //Zeilenvektoren { for (int j = 0; j < getCols(); ++j) { mat[i][j] = m.mat[i][j]; //Werte kopieren } } return *this; } CMatrix& CMatrix::operator+=(const CMatrix& m) { if (getCols() == m.getCols() && getLines() == m.getLines() ) { for (int i = 0; i < getLines(); ++i) { for (int j = 0; j < getCols(); ++j) { mat[i][j] += m.mat[i][j]; } } } return *this; } void CMatrix::print() const //Bildschirmausgabe { for (int i = 0; i < getLines(); i++) { for (int j = 0; j < getCols(); ++j) { cout << mat[i][j] << " "; } cout << endl; } } void CMatrix::setWert(int z, int s, double WertTmp) { mat[z][s] = WertTmp; //und Werte kopieren } double CMatrix::sum(void) const { double sum = 0.0; //Wert zurueck setzen for(size_t i = 0; i < mat.size(); i++) { sum = accumulate( mat[i].begin(), mat[i].end(), sum ); } return sum; } double CMatrix::getWert(int z, int s) const { return mat[z][s]; } [/PHP] Hab es auch zum laufen gebracht, meine berechneten Werte stimmen, aber das Programm wird immernoch folgendermaßen beendet: Das Programm "[3472] test21.exe: Systemeigen" wurde mit Code 0 (0x0) beendet. Da ich im main mit [PHP]int _tmain(int argc, _TCHAR* argv[]) { return 0; } arbeite, dürfte das doch nicht passieren, oder? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
mars12 Geschrieben 8. Dezember 2008 Autor Teilen Geschrieben 8. Dezember 2008 Uups, sorry, habs verpeilt. War noch im Debugmodus! *peinlich* 1000 Dank erstmal - das hat mich gerettet :e@sy Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 8. Dezember 2008 Teilen Geschrieben 8. Dezember 2008 Der Exitcode 0 signalisiert üblicherweise, dass alles in Ordnung war. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.