Problem mit get-Methode
-
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); };
-
ihr würded also empfehlen, die Benennung der Member und Funktionsparameter beizubehalten?
Wir haben gar nix empfohlen und auch nichts suggeriert. Ich würde beispielsweise, tatsächlich um ein schnelleres Verstehen des Codes zu fördern, die Funktionsparameter mit Unterstrichen o.ä. entsprechend Kennzeichnen. Wichtig ist, dass man diesen Stil dann konsequent beibehält.
-
Sone schrieb:
Ich würde beispielsweise, tatsächlich um ein schnelleres Verstehen des Codes zu fördern, die Funktionsparameter mit Unterstrichen o.ä. entsprechend Kennzeichnen. Wichtig ist, dass man diesen Stil dann konsequent beibehält.
Bitte nicht schon wieder diese Diskussion!
Ich würde generell nicht n und m verwenden, sondern irgendetwas wie width, height oder rows, columns oder so.
-
Nathan schrieb:
Sone schrieb:
Ich würde beispielsweise, tatsächlich um ein schnelleres Verstehen des Codes zu fördern, die Funktionsparameter mit Unterstrichen o.ä. entsprechend Kennzeichnen. Wichtig ist, dass man diesen Stil dann konsequent beibehält.
Bitte nicht schon wieder diese Diskussion!
Ich würde generell nicht n und m verwenden, sondern irgendetwas wie width, height oder rows, columns oder so.Aha, du hast keine Lust auf die Diskussion, förderst sie aber durch deine Anteilnahme...
Persönlich könnte ich die Variablen leichter ihrem Zweck zuordnen, wenn ich sie auf die Membervariablen "abbilden" kann, aber das ist Geschmackssache.
(Dementsprechend würde ich auch den Member zumWidth& co. o.ä. umbenennen)
-
Sone schrieb:
Aha, du hast keine Lust auf die Diskussion, förderst sie aber durch deine Anteilnahme...
Nein, ich meine die "Membervariablen mit m, m_, _ vorne, _ hinten oder gar nicht kennzeichnen und Parallelen zur Ungarischen Notation"-Diskussion.
-
Sone schrieb:
Noch einmal: Da ist für den Compiler alles völlig klar.
Wenn nun für den Compiler alles völlig klar ist, warum geht dann mein Code nicht?
Wo ist denn nun der Fehler?
Ahhhh!
Ich inkrementiere m, nicht i. Das war der Fehler!
-
Wenn nun für den Compiler alles völlig klar ist, warum geht dann mein Code nicht?
WTF?
