Operatorüberladung (+=) und Vektoradditiion


  • Mod

    //Tausche maximale Reihe mit der aktuellen Reihen (Spalte für Spalte)
            for (int k=i; k<n+1;k++) {
                double tmp = matrixReduz[maxReihe][k];
                matrixReduz[maxReihe][k] = matrixReduz[i][k];
                matrixReduz[i][k] = tmp;
            }
    

    Wieso n+1 ?



  • Ist dein Konstruktor so vollständig?

    Matrix (vector< vector<double> > matrix):
        matrixVektor(zeilenDim, vector<double>(spaltenDim)) {}
    

    Woher soll der Aufruf matrixVektor zeilenDim und spaltenDim kennen? Ich tippe mal, dass deine Klasse Matrix Membervariablen zeilenDim und spaltenDim hat, die du aber zu dem Zeitpunkt des Aufrufes noch nicht initialisiert hast.



  • Ich musste nocheinmal alles überarbeiten 🙄
    Der Typ des 2D vektors soll nicht double, sondern Zeile sein.
    In der Klasse Zeile lese ich die Zeilen ein und speichere sie als Membervariable (double Vektor).

    Ich will euch nicht den gesamten Code vor die Füße klatschen, deswegen beschränke ich mich aufs wesentliche. Wenn es nötig ist, poste ich natürlich auch alles. 😃

    class Zeile {
    private:
        //Friend-Klasse
        friend class Matrix;
        vector <double> zeilenElemente = {};
        int anzahlZeilenElemente;
    ...
    

    So, jetzt lese ich im Konstruktor die Matrix ein.
    Aufgabenstellung:

    "Im Konstruktor werden Zeilendimension sowie Spaltendimension und Datei übergeben, aus welcher die Matrixeinträge gelesen werden"

    Ich verstehe es so, dass ich zum Einlesen keine eigene Methode erstellen muss sondern das alles im Konstruktor ablaufen soll.
    Geht das vieleicht auch schöner?
    Also so dass ich den Code in die .cpp schreiben kann? 😕

    Mein eigentliches Problem ist folgendes:
    Ich muss jetzt also einen Vektor aus Objekten der Klasse Zeile erstellen. Das funktioniert aber leider nicht wegen push_back 😡 (denke ich)

    Matrix.h:53:43: error: no matching function for call to 'std::vector<std::vector<Zeile> >::push_back(Zeile&)'

    Ich hab gelesen, dass ich für push_Back einen Kopierkonstruktor brauche. Den habe ich auch geschreiben.

    Zeile(const Zeile& x) :
        zeilenElemente(x.zeilenElemente),
        anzahlZeilenElemente(x.anzahlZeilenElemente) {
        }
    

    Aber es will einfach nicht funktionieren. Ich habe die Lösung mit Pointern auch schon probiert aber alles ohne Erfolg 😞 😞

    //Konstruktor
        Matrix(int _zeilenDim, int _spaltenDim, ifstream &f_in) :
        zeilenDim(_zeilenDim),
        spaltenDim(_spaltenDim),
        matrixVektor(_zeilenDim, vector<Zeile>(_spaltenDim)) {
    
            //2d Vektor deklarieren
            vector< vector<Zeile> > tempMatrix;
    
            //zwei zeile Überspringen
            string getlineDummy;
            bool abgefragt = true;
            if (abgefragt) {
                for (size_t i = 0; i < 2; i++) getline(f_in, getlineDummy);
                abgefragt = false;
            }
    
            // 2d Vektor füllen
            for (int i = 0; i < zeilenDim; i++) {
    
              Zeile zeileObjekt;
    
              zeileObjekt.Einlesen(5,f_in);
              tempMatrix.push_back(zeileObjekt);
    
            }
    
            //this ->matrixVektor = tempMatrix;
        }
    


  • Philipp2706 schrieb:

    So, jetzt lese ich im Konstruktor die Matrix ein.
    Aufgabenstellung:

    "Im Konstruktor werden Zeilendimension sowie Spaltendimension und Datei übergeben, aus welcher die Matrixeinträge gelesen werden"

    Ich verstehe es so, dass ich zum Einlesen keine eigene Methode erstellen muss sondern das alles im Konstruktor ablaufen soll.
    Geht das vieleicht auch schöner?
    Also so dass ich den Code in die .cpp schreiben kann? 😕

    Da bin ich jetzt confused. Natürlich kannst du Konstruktor-Code in die cpp-Datei schreiben, da gehört er nämlich normalerweise auch hin.

    Philipp2706 schrieb:

    Matrix.h:53:43: error: no matching function for call to 'std::vector<std::vector<Zeile> >::push_back(Zeile&)'

    du willst einen std::vector<zeile>, nicht einen std::vector<std::vector<zeile>>. Das wäre dann nämlich schon dreidimensional.

    Philipp2706 schrieb:

    Ich hab gelesen, dass ich für push_Back einen Kopierkonstruktor brauche. Den habe ich auch geschreiben.

    Zeile(const Zeile& x) :
        zeilenElemente(x.zeilenElemente),
        anzahlZeilenElemente(x.anzahlZeilenElemente) {
        }
    

    Aber es will einfach nicht funktionieren. Ich habe die Lösung mit Pointern auch schon probiert aber alles ohne Erfolg 😞 😞

    Da wäre jetzt die Definition von "zeile" wichtig. Wenn das Ding nur aus einem std::vector<double> besteht, ist der automatisch generierte Kopierkonstruktor vollkommen ausreichend.
    Btw. wenn du std::vector benutzt, musst du die Anzahl der Elemente nicht zusätzlich noch speichern.



  • daddy_felix schrieb:

    Da bin ich jetzt confused. Natürlich kannst du Konstruktor-Code in die cpp-Datei schreiben, da gehört er nämlich normalerweise auch hin.

    okay das würde dann schon etwas ordentlicher aussehen 🙂
    Muss der ganze Konstruktor in die .cpp oder kann/soll man den Konstruktor irgendwie auftrennen?
    als Beispiel:

    Zeile() :
        zeilenElemente(), //Initialisierungsliste in die Header datei
        anzahlZeilenElemente() {
    //Dieser Bereich in die .cpp
        }
    

    daddy_felix schrieb:

    du willst einen std::vector<zeile>, nicht einen std::vector<std::vector<zeile>>. Das wäre dann nämlich schon dreidimensional.

    danke!! 👍 🙂

    daddy_felix schrieb:

    Btw. wenn du std::vector benutzt, musst du die Anzahl der Elemente nicht zusätzlich noch speichern.

    Im Aufgabentext steht, dass das Objekt die Länge der Zeile zur Verfügung stellen soll, also muss ich diese Länge als Membervariable speichern richtig?



  • Den Konstruktor nicht aufteilen. Wird dir der Kompiler auch sagen. Wie jede Funktion, Deklaration im Header, Implementation in der Cpp.

    Wenn deine Klasse 'Zeile' die Anzahl der Elemente zur Verfügung stellen soll, kann das entweder über eine Membervariable erfolgen, oder durch eine Funktion, die die Vektorgröße zurück gibt. 😉



  • Schlangenmensch schrieb:

    Den Konstruktor nicht aufteilen. Wird dir der Kompiler auch sagen. Wie jede Funktion, Deklaration im Header, Implementation in der Cpp.

    Okay..gut zu wissen 🙂

    Es folgt auch direkt das nächste Problem 😃 Ich tue mich noch echt schwer mit Klassen.

    Ich zerbreche mir gerade den Kopf darüber wie ich den Vector <Zeile> mit den darin enthaltenen Vektoren <Double> ausgeben kann.
    Ich habe es mit einem Umweg versucht, der die einzelnen Zeilen, mit Hilfe von zwei Getter-Methoden, aus der Klasse Zeile in die Operatorüberladungsmethode überträgt.

    //Getter Methode in Klasse Zeile
        vector <double> gib_zeilenElemente() const {
            return (zeilenElemente);
        }
    
    //Getter Methode in Klasse Matrix
        vector <double> gib_zeilenElemente() const {
            Zeile zeileObjekt;
            return (zeileObjekt.gib_zeilenElemente());
        }
    

    Allerdings kann hier nicht auf ein Element des Rückgabewertes der Getter-Methode zugegriffen werden.
    Netbeans gibt keine Fehlermeldung.

    ////Operatorüberladung  
    ostream &operator<<(ostream &ostr, const Matrix& matrixElement) {
        for ( size_t i = 0; i < matrixElement.zeilenDim; ++i ) {
           vector <double> ostrVektor =matrixElement.gib_zeilenElemente();  
           for (int j = 0; j < matrixElement.spaltenDim; ++j) {    
           ostr << "        " << ostrVektor.at(j);
            }
            cout << endl;
        }
     return ostr;
    }
    

    Das steht in der Main:

    try {
        Matrix A(4,5,f_in);
        cout << "A: " << A.gib_m() << "x" << A.gib_n() << endl;
        cout << A << endl;
    ...
    

    Gibt es auch eine Möglichkeit das 2D Array direkt auszulesen?
    Kann mein Ansatz überhaupt funktionieren??

    Danke:)

    Achja

    Schlangenmensch schrieb:

    Wenn deine Klasse 'Zeile' die Anzahl der Elemente zur Verfügung stellen soll, kann das entweder über eine Membervariable erfolgen, oder durch eine Funktion, die die Vektorgröße zurück gibt. 😉

    Welche dieser Varianten ist denn die "schönere"?



  • Haha ich hab es hingekriegt 🙂 🙂

    Ich habe für beide Klassen den Operator [] überladen und das hier in die verschachtelten for Schleifen geschrieben:

    ostr << "        " <<matrixElement[i].gib_zeilenElemente()[j];
    

    Ich habe noch eine Frage..

    const Zeile& Matrix::operator[](int index) const{
    

    So sieht meine Operatorüberladung aus. Kann man die const so schreiben.
    Das sieht etwas seltsam aus vorne und hinten const zu schreiben finde ich.



  • Philipp2706 schrieb:

    const Zeile& Matrix::operator[](int index) const{
    

    So sieht meine Operatorüberladung aus. Kann man die const so schreiben.
    Das sieht etwas seltsam aus vorne und hinten const zu schreiben finde ich.

    Sieht nicht seltsam aus, sondern das muss so.

    Hinten: die Funktion ändert das Matrix-Objekt selbst nicht. Wenn das const hinten nicht da wäre, könntest du den Operator nicht bei konstanten Matrix-Objekten benutzen.
    Vorn: der Rückgabewert ist eine Referenz auf einen konstanten Wert (wenn das const vorn nicht da wäre, könnte man ja non-const Methoden der Zeile aufrufen, die wiederum das Matrix-Objekt ändern würden. Dies widerspräche dem hinteren const).

    Vielleicht möchtest du den Operator auch noch non-const überladen, sodass du die Zeile auch ändern kannst. Dann 2x das const weg.



  • In diesem Zusammenhang ist bei mir noch ein Fehler aufgetreten.
    Ich würde gerne aus dem <Zeile> Vektor ein 2D double Array machen.

    Ich kann den double Wert aber einfach nicht im Array speichern 😮 😕

    In einer double Variable geht es schon.

    Ich habe mir gedacht dass es mit dem const in der Operatorüberladung zusammenhängen kann. Deswegen habe ich den Operator noch zusätzlich ohne const überladen aber es klappt immer noch nicht.

    Irgendjemand eine Idee woran das liegen könnte?

    Ich hab das mal ganz kleinschrittig gemacht. Die Zeile " matrixDouble[i][j]=a;" macht Probleme.

    for (int i = 1; i < 3; ++i) {
            for (int j = 1; j < 3; ++j){
                double a=matrixElement[i].gib_zeilenElemente()[j];
             matrixDouble[i][j]=a;
                cout << a;
            }    }
    

    Edit: Hat sich erledigt. Ich habe einfach ein Array statt eines Vektors genommen. So funktioniert es, warum auch immer 😃


Anmelden zum Antworten