Problem mit get-Methode
-
Da du anscheinend manuelle Speicherverwaltung benutzt, wirst du dabei wohl etwas falsch gemacht haben. Schon alleine die Benutzung roher Zeiger bei offensichtlicher Verletzung der Dreierregel zeigt, dass da schon bei den Grundlagen etwas nicht stimmt. Warum überhaupt manuelle Speicherverwaltung? Nutz doch einen vector! Warum überhaupt eine Liste von Listen? Eine Matrix kannst du leicht auf eine 1D-Struktur mappen, was viel einfacher und effizienter ist!
Vorschlag: Komplett neu machen. Dieses mal mit folgendem Ansatz:
class matrix { private: size_t size_x, size_y; std::vector<int> data; public: matrix(size_t n, size_t m); // ~matrix(); Brauchst du nicht mehr // void print(int n, int m); Anwendungscode. Nicht Aufgabe der Matrixklasse. // void input(); Anwendungscode. Nicht Aufgabe der Matrixklasse. int getVal(size_t n, size_t m) const; // const-correctness beachten! int& getVal(size_t n, size_t m); // Sicherlich auch ganz nützlich, wenn man schreibend zugreifen kann };P.S.: Du hast den Code gepostet, während ich geantwortet habe. Mein Verdacht, dass du mit manueller Speicherverwaltung hantierst und dabei alles falsch machst, bestätigt sich.
-
An die Sache mit den Vektoren hab ich auch schon gedacht. Ich soll aber eigene Felder benutzen!
Von daher kann ich leider mit deinem Tip nicht viel anfangen. Wäre daher nett, wenn du mir sagen könntest, wo der Hase im Pfeffer liegt!
-
int operator[]( std::array<int, 2> const& indices ) const; // const-correctness beachten! int& operator[]( std::array<int, 2> const& indices ) // Sicherlich auch ganz nützlich, wenn man schreibend zugreifen kannFTFY

(Mit init-list benutzen, ginge aber natürlich auch mit dem Funktionsoperator)
-
Habt ihr denn nicht gelernt wie das geht, wenn ihr das selber machen sollt? Die Regel der großen Drei wurde schon genannt. Wahrscheinlich ist noch viel mehr falsch, weil man vieles falsch machen kann und du nicht alles gezeigt hast. Aber wir können dir hier nicht alles beibringen, worauf es ankommt. Im Prinzip ist deine erste Aufgabe, std::vector nachzuprogrammieren. Dazu brauchst du mindestens schon einmal folgende Stichworte:
http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)
http://en.wikipedia.org/wiki/RAIIWenn das fertig und getestet(!) ist, dann bastelst du damit deine Matrixklasse. Und zwar wirklich nur 1D! Das 2D zu machen ist (fast immer*) Unsinn.
*: Diese Relativierung bezieht sich nicht auf die hier vorliegende Aufgabe. Naturwissenschaftler mögen keine absoluten Aussagen, wenn sie nicht in jedem Fall stimmen. Die Relativierung ist für die Klugscheißer im Forum gedacht, die ansonsten einen Flamewar starten würden, dass sie einen Sonderfall kennen, in dem das sinnvoll ist. Daher nochmal absolute Aussage: Solch ein Fall liegt hier nicht vor. 1D ist angesagt.
Sone schrieb:
int operator[]( std::array<int, 2> const& indices ) const; // const-correctness beachten! int& operator[]( std::array<int, 2> const& indices ) // Sicherlich auch ganz nützlich, wenn man schreibend zugreifen kannFTFY

(Mit init-list benutzen, ginge aber natürlich auch mit dem Funktionsoperator)Wo soll denn da der Vorteil sein, außer, dass es umständlicher+ ist?
+: Ich bin nicht mehr sicher, ob das in C++ als Vorteil oder als Nachteil gilt

-
SeppJ schrieb:
Sone schrieb:
int operator[]( std::array<int, 2> const& indices ) const; // const-correctness beachten! int& operator[]( std::array<int, 2> const& indices ) // Sicherlich auch ganz nützlich, wenn man schreibend zugreifen kannFTFY

(Mit init-list benutzen, ginge aber natürlich auch mit dem Funktionsoperator)Wo soll denn da der Vorteil sein, außer dass es umständlicher ist?

Naja, und außerdem passt es besser. Wenn du eine Matrix auslesen willst, dann nimmst du halt den
operator[].Siehe auch Boost, AFAIR mit
boost::rangemachen die das da....
-
Übrigens: Wie intuitiv ist schon
a.get(1, 2) = 8;Viel lieber:
a[{1, 2}] = 8;
-
So Leute, ich probier's nochmal. Ich würde sehr gerne an meinem Code weiterarbeiten. Vielleicht könnt ihr mich ja auf so manchen Fehler hinweisen? Ich kopier jetzt mal allen Code rein:
#include<iostream> #include"U1A3und4header.h" using namespace std; int main() { matrix matrixLinks(4,4); matrix matrixRechts(4,4); return 0; }#ifndef U1A3UND4HEADER__H #define U1A3UND4HEADER__H class matrix { private: int n, m; int** feld; public: matrix(int n, int m); ~matrix(); void print(int n, int m); void input(); int getVal(); }; #endif#include<iostream> #include"U1A3und4header.h" using namespace std; matrix::matrix(int n, int m) : n(n), m(m) { int** feld = new int*[n] (); //Array allokieren for(int i = 0; i<n ; i++) { feld[i] = new int[m] (); } } matrix::~matrix() { for (int j=0; j<n ; j++) { delete[] feld[j]; } delete[] feld; }Die "getVal"-Methode hab ich nun nochmal gelöscht. Mir fällt nämlich jetzt schon auf, dass der Destruktor den gleichen Fehler wie die getVal-Methode bringt.
Ich denke ein Fehler liegt dann wohl schon am Anfang beim allokieren...
Helft ihr mir?
-
bandchef: Du initialisierst in deinem Konstruktor eine lokale Variable feld und nicht die gleichnamige Membervariable. Dadurch erzeugst du einerseits ein Speicherloch, da der allozierte Speicher niemals freigegeben wird, und andererseits bleibt die Membervariable feld uninitialisiert, so dass es beim Zugriff darauf zu undefiniertem Verhalten kommt.
Was SeppJ sagt, gilt natürlich trotzdem, das ist aber anscheinend nicht die direkte Ursache für dein Problem.
-
NATÜRLICH!
Jetzt fällts mir auch auf! Nur wie kann ich auf das Feld in der Klasse zugreifen?
Edit: So richtig?
matrix::matrix(int n, int m) : n(n), m(m) { this->feld = new int*[n] (); //Array allokieren for(int i = 0; i<n ; i++) { this->feld[i] = new int[m] (); } }
-
...
-
Ich will hier nun eine Methode Coden für eine Matrixmultikplikation. Ich hab auch schon wieder Code dafür:
void matrix::mul(matrix feldLinks, matrix feldRechts) { for (int i=0; i<this->m; m++) //Zeilen durchschalten { for (int j=0; j < this->n; j++) //Spalten durchschalten { for (int inner = 0; inner<this->n; inner++) //Multiplizieren { this->feld[i][j] = this->feld[i][j] + (feldLinks.getVal(i, inner) * feldRechts.getVal(i, j)); } } cout << endl; } }Die Klasse sieht nun mittlerweile so aus:
class matrix { private: int n, m; int** feld; public: matrix(int m, int n); ~matrix(); void print(); void input(); void mul(matrix feldLinks, matrix feldRechts); int getVal(int m, int n); void setVal(int m, int n, int val); };Die main Aufrufe hab ich so gemacht:
matrix matrixLinks(3,3), matrixRechts(3,3), matrixErgebnis(3,3); matrixLinks.input(); matrixRechts.input(); matrixErgebnis.print(); matrixErgebnis.mul(matrixLinks, matrixRechts); matrixErgebnis.print();Problem daran ist nun, dass nach dem Aufruf der vorletzten Zeile in der main das Programm augenblicklich ohne Warnung stehen bleibt. Der Compiler kompiliert fehlerfrei! Was könnte das sein? Riecht irgendwie nach Endlosschleife...
-
ich würde zunächst mal die Membervariablen umbenennen, damit sie anders heißen, als die gleichnamigen Funktionesparameter
int n, m;wenn der Compiler da keinen Drehwurm bekommt, bekommt ihn der menschliche Leser
-
wenn der Compiler da keinen Drehwurm bekommt
Ne, der bekommt gar nix.
ich würde zunächst mal die Membervariablen umbenennen, damit sie anders heißen, als die gleichnamigen Funktionesparameter

Wohl eher andersrum!
-
um herauszufinden, ob der Compiler da einen Drehwurm bekommt, siehe ISO/IEC 14882:2011 3.4 Name lookup S. 45-59 (sind nur ca. 14 Seiten zu durchforsten
)
-
...
-
bandchef schrieb:
void matrix::mul(matrix feldLinks, matrix feldRechts) { for (int i=0; i<this->m; m++) //Zeilen durchschalten ... }m++?
-
Swordfish schrieb:
Wovon soll da irgendwer 'nen Drehwurm bekommen?!
in diesem Konstruktor
matrix::matrix(int n, int m) : n(n), m(m)gelten folgende Regeln:
3.4.1 Unqualified name lookup
11 During the lookup for a name used as a default argument (8.3.6) in a function parameter-declaration-clause or used in the expression of a mem-initializer for a constructor (12.6.2), the function parameter names are visible and hide the names of entities declared in the block, class or namespace scopes containing the function declaration. [ Note: 8.3.6 further describes the restrictions on the use of names in default arguments. 12.6.2 further describes the restrictions on the use of names in a ctor-initializer. —end note ]
12.6.2 Initializing bases and members
2 In a mem-initializer-id an initial unqualified identifier is looked up in the scope of the constructor’s class and, if not found in that scope, it is looked up in the scope containing the constructor’s definition. [ Note: If the constructor’s class contains a member with the same name as a direct or virtual base class of the class, a mem-initializer-id naming the member or base class and composed of a single identifier refers to the class member. A mem-initializer-id for the hidden base class may be specified using a qualified name. —end note ] Unless the mem-initializer-id names the constructor’s class, a non-static data member of the constructor’s class, or a direct or virtual base of that class, the mem-initializer is ill-formed.
12 Names in the expression-list or braced-init-list of a mem-initializer are evaluated in the scope of the constructor for which the mem-initializer is specified. [ Example:
class X {
int a;
int b;
int i;
int j;
public:
const int& r;
X(int i): r(a), b(i), i(i), j(this->i) { }
};
initializes X::r to refer to X::a, initializes X::b with the value of the constructor parameter i, initializes X::i with the value of the constructor parameter i, and initializes X::j with the value of X::i; this takes place each time an object of class X is created. —end example ] [ Note: Because the mem-initializer are evaluated in the scope of the constructor, the this pointer can be used in the expression-list of a mem-initializer to refer to the object being initialized. —end note ]in der mem-initializer-list im Konstrukor kann der Compiler also n und n noch auseinanderhalten, aber spätestens hier ist dann der Wurm drin:
void print(int n, int m);der Compiler führt das dann zwar aus, aber es ist besser, die Member n und m anders zu benennen als die Funktionsparameter, denn in der Funktion print sind die Member n und m hidden und es geschehen merkwürdige Dinge
-
...
-
Noch einmal: Da ist für den Compiler alles völlig klar.
Und auch für den C++-Programmierer: Denn die Faustregel ist: Zuerst werden in inneren, und dann in äußeren Scopes gesucht. Und in der Initialisierungsliste lässt sich anhand der Syntax und logischen Gegebenheiten (wie der, dass Funktionsparameter nicht in der Initialisierungsliste "initialisiert" werden können) eben die jeweiligen Namen deduzieren.
-
ihr würded also empfehlen, die Benennung der Member und Funktionsparameter beizubehalten?
class matrix { private: int n, m; int** feld; public: matrix(int n, int m); ~matrix(); void print(int n, int m); void input(); int getVal(int n, int m); };