Unbekannter fehler Matrizen Multiplizieren


  • Mod

    Photon schrieb:

    Hat jemand n tip wie ich das so optimieren kann das es nicht nur für gleich große Matrizen funtioniert? 😕

    Du musst erstmal mathematisch die Frage klären, was geht und was nicht. Was muss für M, N, O, und P gelten, wenn man eine MxN-Matrix mit einer OxP-Matrix multiplizieren will? Wenn du das beantworten kannst, ergibt sich eigentlich ganz von alleine der nötige Code.

    dann habe ich eben sowas versucht um eine Matrix einfach ber cout darzustellen aber es ging nicht. Gibt's da was besonderes zu beachten?

    void operator<<(){
        
        //magic
        
        }
    

    Ja. Dieser Operator will linksseitig ja ein Objekt vom Typ ostream haben (von dieser Klasse ist cout). Da du der ostream-Klasse nicht einfach irgendwelche Memberfunktionen hinzu fügen kannst, muss es eine freie Funktion sein. Außerdem kann man ostreams nicht kopieren, also müssen diese zwangsläufig als Referenz übergeben werden. Und zu guter Letzt willst du den ostream selbst noch als Rückgabewert zurück geben, damit man mehrere Aufrufe aneinanderreihen kann, a la cout << a << b << c; . Das ist in Wirklichkeit (((cout << a) << b) << c) , jeder Aufruf gibt aber cout selber zurück, daher kann man auf das Ergebnis wieder ein << anwenden. Der Rückgabewert ist auch immens wichtig, wenn du mal einen Eingabeoperator (>>) überladen willst, da darüber die ganze Fehlerprüfung läuft.

    Daher Signatur:

    class foo
    {
      int i;
    };
    
    std::ostream& operator<<(std::ostream &out, const foo& f)
    {
      out << f.i;
      return out;
    }
    

    Doch ein Problem gibt es: i ist ja privat und der Operator aber keine Memberfunktion von foo. Daher gibt es zwei übliche Lösungen:
    1. foo bietet auch noch ein paar public-Funkionen an, die eine Ausgabe erzeugen und die dann vom Operator benutzt werden.
    2. Man macht es als friend.

    Die friend-Syntax wird schnell unübersichtlich, falls foo ein komplizierter Templateausdruck ist. Man denke da dran, dass man friend-Funktionen auch innerhalb der Klasse definieren kann. Sie verhalten sich dann trotzdem wie freie Funktionen (bis auf ein paar Kleinigkeiten bezüglich der Feinheiten der Namensauflösung, für die mir spontan nicht einmal ein Beispiel einfällt, wann es eine Rolle spielen könnte):

    class foo
    {
      int i;
    
      // So passt alles
      friend std::ostream& operator<<(std::ostream &out, const foo& f)
      {
        out << f.i;
        return out;
      }
    };
    

    P.S.: Siehe:
    http://www.c-plusplus.net/forum/232010
    und Google spuckt auch sehr viel zum Thema aus.



  • Das elementweise Matrixprodukt funktioniert nur bei gleich großen Matrizen. Du fragst ja auch nicht, wie du 2 Matrizen mit verschiedener größe addieren kannst. Es macht einfach keinen Sinn.

    nur das "echte" Matrixprodukt kann mit Matrizen unterschiedlicehr Größe klarkommen (aber auch da gibt es Einschränkungen).



  • ok danke

    wie ist das eigentlich bei soner Operator überladen function mit dem lhs kann man den auch als const übergeben?


  • Mod

    Photon schrieb:

    wie ist das eigentlich bei soner Operator überladen function mit dem lhs kann man den auch als const übergeben?

    Es sind die gleichen Regeln wie bei allen Funktionen, nur der Funktionsname ist anders und es ermöglicht eine andere Aufrufsyntax. Du kannst sogar die bekannte Funktionsaufrufsyntax verwenden:

    Foo operator*(const Foo &lhs, const Foo &rhs);
    
    Foo a,b;
    Foo c = operator*(a,b); // Das gleiche wie c = a * b;
    

    Damit sollte sich die Frage nach dem const wohl selbst beantworten: Nutz es, als ob es ganz normale Funktionen mit ganz normalen Parametern wären, mach das const, was du auch dort const machen würdest. Für Implementierungen als Memberfunktion gilt natürlich das gleiche*.

    *: Dir ist schon klar, dass man Memberfunktionen const machen kann, oder? Falls dir die Frage zu dumm vorkommt: Entschuldigung, ich wollte bloß sicher gehen, dass es nicht an den Grundlagen zum const fehlt.



  • Moin,

    Ja SeppJ das das so geht wusste ich ich will aber dann in der main trotzdem diese Schreibweise haben

    Matrix a, b;
    Matrix c=a*b;
    

    Also will ich die memberfunktion so schreiben:

    Matrix Operator*(const Matrix& rhs){...
    

    In dem fall übergebe ich den lhs ja nicht direkt aber ich hätte ihn gerne trotzdem const ich hoffe ihr versteht was ich meine.

    Beste Grüße aus dem kalten Berlin
    Photon



  • SeppJ schrieb:

    Dir ist schon klar, dass man Memberfunktionen const machen kann, oder?



  • Du kannst immer wenn du a*b schreibst auch operator*(a,) schreiben. Das hat nichts damit zu tun, ob das Ding nun eine Memberfunktion ist, oder nicht. Aber es hat eine ganze Mnge Vorteile, wenn es _keine_ ist (nämlich automatische konversionsregeln für das linke Argument). Desweiteren kannst du nur so multiplikationsregln wie scalar*matrix implementieren.



  • wenn ich das hier mache bekomm ich ne Fehlermeldung:

    Matrix Operator*(const Matrix& lhs, const Matrix& rhs){...
    
    //dann in der main
    
    Matrix a,b;
    
    Matrix c=a*b;
    

    ||=== Matrizen1, Debug ===|
    H:\projekte\Matrizen1\main.cpp|29|error: 'matrix matrix::operator*(const matrix&, const matrix&)' must take either zero or one argument|
    H:\projekte\Matrizen1\main.cpp||In function 'int main()':|
    H:\projekte\Matrizen1\main.cpp|50|error: no match for 'operator*' in 'a * b'|
    ||=== Build finished: 2 errors, 0 warnings (0 minutes, 30 seconds) ===|

    Ich glaub ich steh hier voll auf dem schlauch 😕


  • Mod

    Photon schrieb:

    Ich glaub ich steh hier voll auf dem schlauch 😕

    class foo
    {
    public:
      void bar() {}
    };
    
    int main()
    {
      const foo f;
      f.bar();
    }
    

    Was fehlt in Zeile 4, damit dieser Code ausführbar wird?

    Wenn du dich wieder an deine Grundlagen zu konstanten Memberfunktionen erinnert hast 🙂 , dann wendest du diese auf deine Operatoren an. Wie gesagt: Das sind ganz normale Funktionen, da wird auch const bzw. nicht-const nach den üblichen Regeln benutzt.



  • Die Funktion sollte so aussehen:

    class foo
    {
    public:
      void bar() const {}
    };
    
    int main()
    {
      const foo f;
      f.bar();
    }
    

    hahahaha danke.

    Also wenn ich ein const objekt habe muss ich es der Funktion auch const übergeben richtig?


  • Mod

    Photon schrieb:

    Also wenn ich ein const objekt habe muss ich es der Funktion auch const übergeben richtig?

    Ich bin mir nicht sicher, was du mit dieser Frage meinst. Du kannst konstante Objekte nicht in einem Kontext benutzen, in dem ein nicht-konstantes Objekt erwartet wird. Umgekehrt (zumindest bis zu einem gewissen Grad) schon. Aber das wusstest du vermutlich schon. Was genau möchtest du wissen? Weißt du nun, wie die linke Seite eines als Memberfunktion überladenen Operators auch konstant sein kann?



  • ja genau das wollte ich wissen 👍

    und ja ich weiss jetzt wie die linke seite const sein kann. So wie in der Funktion da von dir 🙂


Anmelden zum Antworten