Hallo,
ich habe ein Problem mit dem operator overloading.
ich habe 2 Matrizen die ich in der main() addieren möchte,
Matrix x;
Matrix y;
Matrix result;
// eingabe wird über cin>> gehandelt...
x.a[2][2] = {{2, 2}, {2, 2}}
y.a[2][2] = {{1, 2}, {3, 4}}
result=x+y; // result soll {{3,4},{5,6}} ausgeben
1 | class Matrix{
| 2 | public:
| 3 | std::vector<std::vector<int>> a;
| 4 | Matrix operator+(const Matrix& f_object)
| 5 | {
| 6 | Matrix result;
| 7 | int i = 0;
| 8 |
| 9 | for(int y = 0; y<a.size(); y++)
| 10 | {
| 11 | for(int z = 0; z<a[y].size(); z++)
| 12 | {
| 13 | cout<<"a[y][z]: "<<a[y][z]<<endl;//dieser Kommentar wird noch angezeigt
| 14 | result.a[y][z]=(a[y][z] + f_object.a[y][z]); // hier kommt der Absturz
| 15 | cout << "f_object.a["<<y<<"]"<<"["<<i<<"]: "<< f_object.a[y][i] << endl; // dieser Kommentar nicht mehr
| 16 | }
| 17 | }
| 18 | return result;
| 19 | }
| 20 | };
|
habe ich was übersehen,
Wie stellst Du sicher, dass a und f_object.a die selbe Dimension haben?
Du nimmst die Größe der ersten Dimension von f_object.a und die Größe
der zweiten Dimension von a als Iterationsgrenzen für beide Arrays. Was
passiert, wenn die erste Dimension von a aber kleiner ist als von
f_object.a...
Andreas M. schrieb:
> Wie stellst Du sicher, dass a und f_object.a die selbe Dimension
> haben?
> Du nimmst die Größe der ersten Dimension von f_object.a und die Größe
> der zweiten Dimension von a als Iterationsgrenzen für beide Arrays. Was
> passiert, wenn die erste Dimension von a aber kleiner ist als von
> f_object.a...
hast natürlich recht, habe jetzt überall a als Referenz genommen.
die Grössen der Matrizen sind fest definiert, daher checke ich zur Zeit
nicht ob die Grösse gleich ist.
also so funktioniert es, ich verstehe aber nicht ganz warum der 2D Array
Ansatz nicht tut; 1 | Matrix operator+(const Matrix& f_object)
| 2 | {
| 3 | Matrix result;
| 4 | int i = 0;
| 5 |
| 6 | for(int y = 0; y<a.size(); y++)
| 7 | {
| 8 | std::vector<int> temp;
| 9 | for(int z = 0; z<a[y].size(); z++)
| 10 | {
| 11 | // result.a[y][z]=(a[y][z] + f_object.a[y][z]);
| 12 | temp.push_back(a[y][z] + f_object.a[y][z]);
| 13 | }
| 14 |
| 15 | result.a.push_back(temp);
| 16 | }
| 17 | return result;
| 18 | }
|
Was soll denn passieren, wenn Du Matrizen unterschiedlicher Dimension
addierst? Diese Frage solltest Du Dir als erstes beantworten.
Wenn Du dann zu dem Schluss kommst, dass das sinnlos ist, solltest Du
das Du das Typsystem unterbinden.
Wilhelm M. schrieb:
> Wenn Du dann zu dem Schluss kommst, dass das sinnlos ist, solltest Du
> das Du das Typsystem unterbinden.
Da würde sich anbieten, "Matrix" als Template-Klasse anzulegen, mit den
Dimensionen und dem Datentyp als Template-Parameter.
Ansonsten: auch wenn "this" und "f_objekt" beides 2×2-Matrizen sind,
"Matrix result;" ist es nicht.
Michael S. schrieb:
> also so funktioniert es, ich verstehe aber nicht ganz warum der 2D Array
> Ansatz nicht tut;
Weil result.a die Dimension (0,0) hat. Du musst result.a schon
initialisieren. std::vector ist ein dynamisches array.
Kleine Ergänzung:
1 | #include <iostream>
| 2 | #include <vector>
| 3 | #include <type_traits>
| 4 | template <size_t rows, size_t cols, typename T>
| 5 | requires std::is_arithmetic_v<T>
| 6 | class Matrix {
| 7 | // ...
| 8 | };
|
Denn ein 1 | Matrix<42, 43, std::string>
|
macht ggf. wenig Sinn.
ahhh, d.h. wenn ich über push_back gehe, brauche ich keine Grösenangaben
zum Array. Wenn aber Zuweisung über die einzelnen Elemente statt findet,
dann muss zuerst die Initialisierung her.
PS. danke fürs Template
Wilhelm M. schrieb:
> Denn ein
> Matrix<42, 43, std::string>
> macht ggf. wenig Sinn.
Stimmt natürlich. Würde aber Kompilieren :)
1 | Matrix<3, 3, std::string> matrixA({ {"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"} });
| 2 | Matrix<3, 3, std::string> matrixB({ {"9", "8", "7"}, {"6", "5", "4"}, {"3", "2", "1"} });
| 3 |
| 4 | Matrix<3, 3, std::string> matrixC = matrixA + matrixB;
| 5 |
| 6 | std::cout << "Matrix A:\n" << matrixA;
| 7 | std::cout << "Matrix B:\n" << matrixB;
| 8 | std::cout << "Matrix C (A + B):\n" << matrixC;
|
--> 1 | Matrix A:
| 2 | 1 2 3
| 3 | 4 5 6
| 4 | 7 8 9
| 5 | Matrix B:
| 6 | 9 8 7
| 7 | 6 5 4
| 8 | 3 2 1
| 9 | Matrix C (A + B):
| 10 | 19 28 37
| 11 | 46 55 64
| 12 | 73 82 91
|
🤡
Und da die Matrix dann compilezeit-konstant in ihrer Größe ist, wäre
natürlich ein std::array als Container besser.
Michael S. schrieb:
> PS. danke fürs Template
Hier noch eine Ergänzung für die Klasse: 1 | Matrix<cols, rows, T> transpose() const {
| 2 | Matrix<cols, rows, T> result;
| 3 |
| 4 | for (size_t i = 0; i < rows; i++) {
| 5 | for (size_t j = 0; j < cols; j++) {
| 6 | result[j][i] = data[i][j];
| 7 | }
| 8 | }
| 9 |
| 10 | return result;
| 11 | }
|
Für den Lern-Effekt, wie dir der Compiler mit Templates da hilft Fehler
schon zur Compile-Zeit zu vermeiden. Für Nicht-Quadratische Matrizen
gibt transpose einen anderen Datentyp zurück...
Wilhelm M. schrieb:
> Und da die Matrix dann compilezeit-konstant in ihrer Größe ist, wäre
> natürlich ein std::array als Container besser.
Psst, nicht zuviele Neuerungen auf einmal. Aber würde den Code sogar
einfacher machen.
1 | private:
| 2 | std::array<std::array<T, cols>, rows> data;
|
Und der Matrix()-Konstruktor hat dann nix mehr zu tun.
Man kann sogar noch etwas weiter gehen und bspw.
1 | Matrix<2, 3, float> a;
| 2 | Matrix<2, 3, double> b;
| 3 |
| 4 | auto c = a + b;
|
möglich machen. Dann ist man bei TMP und muss / sollte eine Metafunktion
F(T1, T2) -> T schreiben, also etwa F<float, double> -> double.
Εrnst B. schrieb:
> Und der Matrix()-Konstruktor hat dann nix mehr zu tun.
Falls Du den cctor meinst: nein.
Wilhelm M. schrieb:
> Εrnst B. schrieb:
>> Und der Matrix()-Konstruktor hat dann nix mehr zu tun.
>
> Falls Du den cctor meinst: nein.
Ich weiß nicht, was das sein soll, aber er meint offenbar den
default-Konstruktor Matrix() (wie er ja auch schreibt), der in der
aktuellen Version dafür sorgt, dass die Vektoren ihren Speicher
allokieren.
Rolf M. schrieb:
> Wilhelm M. schrieb:
>> Εrnst B. schrieb:
>>> Und der Matrix()-Konstruktor hat dann nix mehr zu tun.
>>
>> Falls Du den cctor meinst: nein.
>
> Ich weiß nicht, was das sein soll,
die übliche Bezeichnung für copy-constructor
> aber er meint offenbar den
> default-Konstruktor Matrix() (wie er ja auch schreibt), der in der
> aktuellen Version dafür sorgt, dass die Vektoren ihren Speicher
> allokieren.
... den ich dann irgendwie übersehen hatte ...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|