Problem mit Überladung von !



  • probier auch hier *this zurückzugeben



  • Bei so vielen Beiträgen hätt ich gedacht, dass du schon recht erfahren bist, aber anscheinend kommst du immer noch nicht mit Pointern und Objekten zu Recht. Sowas gibts in Java nicht, vielleicht ist das das Problem? Shape1 und Shape2 sind Zeiger, da wird dein Operator nicht verwendet. Dafür brauchst du Objekte, also z.B. indem du die Zeiger dereferenzierst. Dass es dann funktioniert kann ich dir nicht garantieren, hab mir jetzt deinen Code nicht genau angeschaut.



  • Mechanics schrieb:

    anscheinend kommst du immer noch nicht mit Pointern und Objekten zu Recht [sic]

    Ergänzend dazu: Modern C++



  • 👍 Vielleicht erst lernen was Zeiger und Referenzen sind, dann anfangen mit Operatorüberladungen rumzuspielen. Spart dir viel sinnlosen Ärger. :xmas1:



  • Die Anzahl der Beiträge sagt eben nicht viel über die Erfahrung aus. Da ich schon länger nicht mehr C++ programmiert habe, habe ich in der Tat Probleme mit Pointern.

    Ich verstehe jedoch deinen Punkt nicht. Hier noch einmal der Code:

    Bild* operator&(Bild* p) {
     return this;
    }
    
    Bild* b1 = new Bild();
    Bild* b2 = new Bild();
    
    b1 = b1 & b2;
    

    Der Operator & bekommt einen Zeiger auf ein Bild Objekt. b2 ist aber doch ein Zeiger. Daher sollte das nicht das Problem sein.

    error: invalid operands of types ‘Bild*’ and ‘Bild*’ to binary ‘operator&’

    Könnt ihr mir denn helfen bei der Fehlerbehebung?
    Danke!



  • Könnt ihr mir denn helfen bei der Fehlerbehebung?

    Ganz einfach, verzichte auf die Pointer.

    Bild b1;
    Bild b2;
    
    b1 = b1 & b2; // et voilà
    


  • Das ist aber doof, weil die Funktionm, in der ich die Berechnungen durchführe ein Bild* zurückgibt. Somit könnte ich Bild Instanzen nicht mehr lokal anlegen. Wie sieht denn die Zeigerlösung aus?



  • Dann lass die Funktion halt keinen Pointer zurückgeben. Langsamer wird dein Code dadurch nicht (copy elision).



  • Bild* b1 = new Bild();
    Bild* b2 = new Bild();
    
    b1 = b1 & b2;
    

    Das Problem ist, dass du hier zwei Bild * mit dem Operator & verknüpfst. Der &-Operator ist aber für Bild * (und sonstige Pointer) nicht definiert. Du willst nicht die Pointer verunden, sondern die Bilder.

    Bild* b1 = new Bild();
    Bild* b2 = new Bild();
    
    b1 = (*b1) & (*b2);
    

    b1 ist ein Pointer, (*b1) ist ein Bild, verunden von Pointern geht nicht, verunden von Bildern geht.

    Bild* operator&(Bild* p) {
     return this;
    }
    

    Das sieht so aus, als wolltest du das Verunden zwischen Bild-Pointern definieren. Das geht nicht. Pointer sind eingebaut, eingebauten Datentypen kann man ihre Operatoren nicht überladen. Du musst schon den &-Operator für Bilder definieren, nicht für Bildpointer.

    Bild operator&(const Bild &b){
        Bild neuesBild = generiereIrgendwieNeuesBildAusThisUndb(this, &b);
        return neuesBild;
    }
    


  • Ersteinmal musst du natürlich nicht überall mit Zeigern rumhantieren, da haben die anderen Teilnehmer Recht, das hier ist halt kein Java, wo es keine andere Möglichkeit gibt.
    Aber was mich jetzt wundert ist deine Argumentation, dass du operator! benutzen musst, weil du einen Term parsen willst, in dem ein ! vorkommt. Was hat denn das Parsen eines Quellcode-fernen Terms mit dem Aufbau des Quellcodes zu tun? Dir fliegt gerade wegen Deiner Affinität zu Zeigern deren implizite Konvertierbarkeit zum Typ 'bool' um die Ohren, da sollte man vielleicht nicht auch die ganzen Operatoren verwenden, die leider auch für bool definiert sind.



  • nwp3 schrieb:

    Bild operator&(const Bild &b){
        Bild neuesBild = generiereIrgendwieNeuesBildAusThisUndb(this, &b);
        return neuesBild;
    }
    

    Ich habe deine Idee mal versucht durchzuführen, aber leider haben sich meine Befürchtungen bewahrheitet. Bei dir ist nun das Problem, dass Du "neuesBild" zurückgibst, obwohl dieses eine lokale Variabel ist. Damit wird diese nach dem Ausführen der Funktion gelöscht und alles führt zu einem Segmentation Fault. Nun bringt es auch nichts "neuesBild" als Klassenvariabel einzuführen, weil die Operationen in verschiedenen Klassen durchgeführt werden. Kann man so überhaupt ganze Objekte zurückgeben?

    Deswegen habe ich eben Zeiger benötigt.

    Gibt es doch eine Lösung, wie ich dieses letzte Problem beheben kann oder muss ich doch auf Zeiger umsteigen?

    Vielen Dank
    LG, freakC++-



  • Ist doch egal, ob die Variable aus dem Scope geht, sie wird ja per Wert und somit als Kopie zurückgegeben. Es sei denn, du hast jetzt wieder einen Zeiger aus dem Rückgabewert gemacht...



  • freakC++ schrieb:

    Bei dir ist nun das Problem, dass Du "neuesBild" zurückgibst, obwohl dieses eine lokale Variabel ist.

    Das ist kein Problem, sondern völlig in Ordnung. Das Problem dürfte eher sein, dass die Bild-Klasse keinen ordentlichen Copy-Konstruktor hat.



  • freakC++ schrieb:

    Ich verstehe jedoch deinen Punkt nicht. Hier noch einmal der Code:

    Bild* operator&(Bild* p) {
     return this;
    }
    
    Bild* b1 = new Bild();
    Bild* b2 = new Bild();
    
    b1 = b1 & b2;
    

    Der Operator & bekommt einen Zeiger auf ein Bild Objekt. b2 ist aber doch ein Zeiger. Daher sollte das nicht das Problem sein.

    error: invalid operands of types ‘Bild*’ and ‘Bild*’ to binary ‘operator&’

    Hallo,
    ich versuche dir mal zu erklären, warum das nicht geht:
    1. Du hast eine Klasse definiert. D.h. du hast einen neuen Datentypen definiert.
    2. Du hast innerhalb der Klasse den Operator & überladen.
    3. Dein Datentyp heist Bild. D.h. du hast den Operator & für den Datentypen Bild überladen.
    4. Du schaust dir den Datentyp von b1 und b2 an. Du siehst, dass diese beiden Variablen vom Typ Bild* sind. Wir erinnern uns, dass du den Operator & für den Typ Bild überladen hast. Und warum es nicht geht, dürfte dir jetzt ja klar sein: Datentyp Bild* != Datentyp Bild



  • Hallo zusammen,

    vielen Dank für die zahlreichen Antworten. Ich habe nun Erfolg gehabt, indem zum einen einen korrekten Copy-Konstruktor definiert habe (der hatte tatsächlich noch gefehlt) und zum anderen ein "Bild" zurückgebe.

    Dennoch verstehe ich nicht, warum diese Lösung nicht langsamer sein soll. Ich muss nun immer ein temporäres "Bild" anlegen, das dan zurückgeben wird. Wir bei mir nun nicht ziemlich viel hin und her kopiert. Dieses Problem müsste man mit Zeigern doch eigentlich umgehen, oder?

    Vielen Dank
    LG, freakC++



  • freakC++ schrieb:

    Ich habe nun Erfolg gehabt, indem zum einen einen korrekten Copy-Konstruktor definiert habe (der hatte tatsächlich noch gefehlt) und zum anderen ein "Bild" zurückgebe.

    Hast meinen Link angeschaut? Modern C++. Sofern Bild richtig designt ist (keine internen Zeiger), dürfte es nicht nötig sein, einen Kopierkonstruktor zu schreiben. Poste am besten einmal deine Klasse Bild oder zumindest ihre Membervariablen.

    freakC++ schrieb:

    Ich muss nun immer ein temporäres "Bild" anlegen, das dan zurückgeben wird. Wir bei mir nun nicht ziemlich viel hin und her kopiert. Dieses Problem müsste man mit Zeigern doch eigentlich umgehen, oder?

    Das Problem wird schon umgangen, aber nicht mit Zeigern.
    Zum einen wäre da die Copy Elision, die ich schon genannt habe, du aber scheinbar überlesen hast. Schau mal da: Want Speed? Pass by Value.
    Zum anderen gibt es mit C++11 nun RValue-References.



  • Was man hier noch machen könnte wäre "copy on write shared data". Das verwendet z.B. Qt intern bei sehr vielen Klassen. Ob sich das bei dir lohnt und ob das Sinn macht, weiß ich nicht. In dem konkreten Beispiel von dir sollte copy elision in der Tat reichen. Vielleicht hast du aber noch mehr Use Cases für die Klasse, wo sich shared data dann lohnen würde.





  • kuh schrieb:

    COW ist viel zu komplex und schadet der Performance

    Ja, der Aspekt ist nicht neu. Der Artikel ja auch nicht, er ist von 1999. Bei Qt ist es wohl halbwegs unproblematisch:

    http://doc.qt.digia.com/qt/threads-modules.html#threads-and-implicitly-shared-classes

    Ich denke, wenn man das richtig benutzt, sollte es keine Performance Probleme geben.



  • freakC++ schrieb:

    Hallo zusammen,

    vielen Dank für die zahlreichen Antworten. Ich habe nun Erfolg gehabt, indem zum einen einen korrekten Copy-Konstruktor definiert habe (der hatte tatsächlich noch gefehlt) und zum anderen ein "Bild" zurückgebe.

    Dennoch verstehe ich nicht, warum diese Lösung nicht langsamer sein soll. Ich muss nun immer ein temporäres "Bild" anlegen, das dan zurückgeben wird. Wir bei mir nun nicht ziemlich viel hin und her kopiert. Dieses Problem müsste man mit Zeigern doch eigentlich umgehen, oder?

    Vielen Dank
    LG, freakC++

    Bild funktion()
    {
        Bild bild;
        baue_bild(bild);
        return bild;
    }
    
    Bild bild = funktion();
    

    baut dir jeder Compiler um zu

    Bild* funktion(void* buf)
    {
        new (buf) Bild;
        baue_bild(*buf);
        return buf;
    }
    
    Byte bild[sizeof(Bild)];
    funktion(bild);
    

Anmelden zum Antworten