Klassen, Operatoren & Reihenfolge



  • hi,

    Ich hab 2 Klassen - Class1 und Class2 - und ich definiere bei jeder der beiden Klassen folgende Operatoren:

    Class1 Class1::operator + (const class Class2 &c) const;
    Class2 Class2::operator + (const class Class1 &c) const;

    Die beiden Operatoren sind logischerweise unterschiedliche Algorithmen. Nun interessiert mich ob der eine Operator (der von Class1) nur dann aufgerufen wird, wenn Class1 mit Class2 addiert wird. Und ob der Operator von Class2 nur aufgerufen wird, wenn Class2 mit Class1 addiert wird! 😕
    Oder bringt das C++ zu sehr durcheinander? 😃

    In der Mathematik spielt es auch eine Rolle in welcher Reihenfolge Objekte verknüpft werden. Wir haben zum Beispiel nur die Multiplikation eines Skalars mit einem Vektor (nicht umgekehrt!) definiert.



  • Oder bringt das C++ zu sehr durcheinander? 😃

    Ich hab's zwar nicht getestet, aber ich denke nicht. Warum auch? Du hast beide Operator-Funktionen definiert (und hoffentlich auch implementiert) und der Compiler wählt dann (jenachdem welches Objekt der Klassen 1 und 2 wo steht, die richtige Operatorfunktion auf).

    KLärt mich ebenfalls auf falls ich mich vertan habe.

    Caipi



  • bluecode schrieb:

    Die beiden Operatoren sind logischerweise unterschiedliche Algorithmen. Nun interessiert mich ob der eine Operator (der von Class1) nur dann aufgerufen wird, wenn Class1 mit Class2 addiert wird. Und ob der Operator von Class2 nur aufgerufen wird, wenn Class2 mit Class1 addiert wird! 😕

    Ja, genau so ist es. 2 Operatoren, die genau das Selbe machen.
    Daher würde ich dir empfehlen, erstmal den operator+ global zu machen.
    Zweitens würde ich an deiner Stelle Konvertierungskonstruktoren anbieten. (also ein Konstruktor mit einem Argument).

    Das könnte nun z.B. so aussehen:

    #include <iostream>
    
    struct bar // zur Vereinfachung nen struct
    {
        int data; // böse *g*
        bar() : data(5)
        {}
        // blub
    };
    
    struct foo // ebenfalls
    {
        int data;
        foo() : data(1)
        {}
        // Konvertierung
        foo(int data) : data(data)
        {}
        foo(const bar& b) : data(b.data)
        {}
        // blabla
    };
    
    const foo operator+(const foo& f, const foo& b)
    {
        return foo(f.data + b.data); // geht natürlich auch über den operator+=
    }
    
    int main()
    {
        foo f;
        bar b;
        // beides ist möglich und ein Operator
        foo a = f + b;
        std::cout << a.data << std::endl;
        a = b + f;
        std::cout << a.data << std::endl;
    }
    


  • Danke für die schnellen Antworten.

    @ChrissiB: Die Idee mit den globalen Operator löst alle meine Probleme und die obere Überlegung auf sehr elegante Weise 👍 . Ich brauche nun nicht mehr bei beiden Klassen die verschiedenen Operatoren definieren, sondern erreiche so:

    const Class1 operator + (const Class1 &c1, const Class2 &c2){/*...*/}
    const Class2 operator + (const Class2 &c2, const Class1 &c1){/*...*/}
    

    Nun existiert doch ein Unterschied zwischen "Class1 + Class2" und "Class2 + Class1"! Oder?



  • bluecode schrieb:

    Danke für die schnellen Antworten.

    @ChrissiB: Die Idee mit den globalen Operator löst alle meine Probleme und die obere Überlegung auf sehr elegante Weise 👍 . Ich brauche nun nicht mehr bei beiden Klassen die verschiedenen Operatoren definieren, sondern erreiche so:

    const Class1 operator + (const Class1 &c1, const Class2 &c2){/*...*/}
    const Class2 operator + (const Class2 &c2, const Class1 &c1){/*...*/}
    

    Nun existiert doch ein Unterschied zwischen "Class1 + Class2" und "Class2 + Class1"! Oder?

    Klar, aber wenn du genauer hinschaust ist das genau das Selbe wie in deinem ersten Post.
    Warum brauchst du unbedingt die beiden +-Operatoren? Die machen doch intern genau das Gleiche, nicht?
    Der Unterschied ist auch bei meiner Version da. Was würdest du machen, wenn du auch noch in Class1 Integer addieren willst? Nochmal 2 neue Operatoren mit Copy&Paste? Was wäre dann, wenn sich auf einmal (zB hat sich der Auftraggeber irgendetwas anderes einfallen lassen) das interne Addieren ändert? Alle 4 Operatoren ändern? ....

    Schaue ein Posting weiter oben, wie ich es gemacht habe. 🕶 Ich habe das Objekt b vom Typ bar an den globalen Operator überwiesen. Dabei würde es aber durch die Konvertierung (Konstruktor) automatisch in ein foo verwandelt (kein explizit angegeben) und kann nun auch als ein foo behandelt werden. Den Rest brauche ich ja nicht mehr erklären. 😉

    Wenn du nun auch eine Zahl (int) addieren willst, machst du einfach einen neuen Konstruktor.

    Natürlich ist es auch möglich, wenn explizit angegeben ist. Dort musst du, wie das Keyword es ja schon sagt, den Typ, in welchen du ihn konvertieren willst, explizit angeben. 😉

    Hoffe das hilft dir nun. 🙂



  • @ChrissiB: Ich möchte in den beiden Operatoren eben NICHT das selbe machen!
    Sonst bräuchte ich nun wirklich nicht 2! 😃



  • Okay, das habe ich nicht gewusst. 🙄



  • Vielleicht verstehst du ja nun mein Problem:
    Werden bei folgendem Codeausschnitt dann verschiedene Operatoren aufgerufen?

    const Class1 operator + (const Class1 &c1, const Class2 &c2){/*...*/}/*Operator1*/
    const Class2 operator + (const Class2 &c2, const Class1 &c1){/*...*/}/*Operator2*/
    
    main()
    {
    class Class1 *cl1 = new Class1();
    class Class2 *cl2 = new Class2();
    cl1 = cl1 + cl2;
    cl2 = cl2 + cl1;
    }
    

    Die Frage ist jetzt ob bei der ersten Addition Operator1 aufgerufen wird und bei der zweiten Operator2!



  • bluecode schrieb:

    Die Frage ist jetzt ob bei der ersten Addition Operator1 aufgerufen wird und bei der zweiten Operator2!

    Eigentlich nicht. Der Compiler müsste meckern. 😉
    1)

    cl1 = *cl1 + *cl2; // es sind zeiger, deferenzieren ;)
    

    Du kannst aber auch einen Zeiger auf die Klassen in der Argumentenliste bei den Operatoren angeben. Dann würde der Zeiger kopiert werden.
    2)

    cl2 = *cl2 + *cl1; // dito
    
    delete cl1, cl2; //löschen net vergessen  :open_mouth:
    
    1. Kannst du das class weglassen
      Wie es aber aussieht (Code), ist das was du suchst, nicht der operator+, sondern eher der operator+=. Der muss in die Klasse, da er ein Argument erwartet.

Anmelden zum Antworten