opaerator []: "cannot be overload" - sollte aber gehen..



  • Hallo!
    Ich versuche mich gerade an Operatorüberladungen..
    Genauer gesagt, will ich den Subscript-Operator zum Lesen u. Schreiben unterschiedlich definieren.
    Btw: Schreiben = "lvalue", Lesen = "rvalue", stimmts?

    Hier mal der Code, und was der Compiler (gcc) dazu sagt:

    class c
    {
    	int a[5];
    
    	public:
    
    	int& operator[](int idx);
    	const int& operator[](int idx);
    
    };
    

    Compiler:"
    error: 'const int& c::operator[](int)' cannot be overloaded|
    error: with 'int& c::operator[](int)'|
    "

    Was muss ich anders machen??

    Gruß,
    Spaghettimann



  • const int& operator[](int idx) const; // const am Ende fehlte
    


  • Rückgabetyp gehört nicht zur Signatur einer Funktion. Du hast demnach 2 gleiche Funktion. Das gibt den Compiler Fehler.



  • ....Aaaahhhaaaaa!!

    Vielen Dank! Das "const" am Ende habe ich zwar schon mal gesehen, mehr aber auch nicht..
    In den Beispielen, die ich so gefunden habe, war davon auch nicht die Rede (u.a. bei stackoverflow -tztztz)

    Was ich mich jetzt noch frage:
    Warum gehört der Rückgabetyp nicht zur Funktionssignatur?!

    Ich habe mir mal gerade die ersten Ergebnisse bei der Suche nach dem const am Ende angesehen. Aber so 100%ig habe ich es noch nicht überblickt..

    Ist das gerade darum vorhanden, weil der Rückgabetyp nicht zur Funktion gehört?!

    Der Einfachheit halber mal ohne Überladungen:

    //Ist:
    const int & func(...) const;
    //..doppelt gemoppelt?!
    
    //Bzw., ist:
    const int & func(...);
    //..==..
    int & func(...) const;
    //..?
    

    Kann mir evtl. jemand den obigen jeweiligen Syntax in Sätze transformieren?!



  • naja wenn man eine Funktion nur an ihrem Rückgabetyp unterscheiden könnte, wird es echt schwierig, die Funktion wieder in eine Funktion einzusetzen.



  • Das const ganz am Ende der Signatur markiert, dass diese Funktion keine Membervariablen verändert. Das heißt man kann diese Memberfunktino auch mit konstanten Objekten aufrufen. Ansonsten geht das nicht, auch wenn die Funktion tatsächlich nichts ändert. Diese Eigenschaft wird im Gegensatz zum Rückgabewert beim Überladen von Funktionen berücksichtig. Wenn es also beide Funktionen gibt und ein nicht const Objekt hat wird die normal Memberfunktion aufgerufen und bei einem konstanten Objekt eben die const Memberfunktion. Dieses Muster findet man eigentlich fast immer bei operator[] Überladungen wieder. Die nicht normale Memberfunktion gibt auch normale Referenzen raus und die const Memberfunktion gibt eben nur const Referenzen. Ist also nicht doppelt gemoppelt sondern genau richtig. Ohne const Rückgabewert dürfte es auch gar nicht compilieren, da die Funktion alle Membervariablen als const sieht und daher auch nur const Referenzen rausgeben kann.



  • Das, was du vorhast - Unterscheidung zwischen Lesen und Schreiben- funktioniert so nicht, eben weil der Returntyp nicht Teil der Signatur ist.
    Das const am Ende funktioniert nur bei Memberfunktionen und erlaubt es sie auf einem konstanten Objekt aufzurufen. Warum dir das vorgeschlagen wurde ist, weil das das häufigste Problem ist. Auf einem nicht konstante Referenz wird Schreibzugriff auf den Member erlaubt, bei einem konstanten nicht.
    Zur Lösung deines Problems brauchst du ein Proxy Objekt, was du anstatt der int Referenz zurückgibst.
    Schreiben ruft dort den operator= auf, lesen den operator int().



  • Sooo, ich habe mich wärend meiner Abwesenheit hier (nebenbei: Sorry dafür) nochmal schlau gemacht..
    ..Und jetzt verstehe ich überhaupt ansatzweise, was man (Nathan) mir hier sagen möchte... Das mit dem const am Ende leuchtet ja recht schnell ein.
    Aber das mit der Proxy-Klassen (und dem Cast-OP, den man offenbar auch zu brauchen scheint), das klingt für mich eher nach einem Workaround für ein eigentlich recht einfaches/alltägliches Problem. Ein zusätzliches Attribut wie "read/write" oder "lvalue/rvalue" würde das rgendwie einfacher gestalten..
    Aber davon mal abgesehen, bin ich ja etwas stolz, so langsam bei dem Teil von c++ anzukommen, der mit Workarounds arbeitet... 🙄
    ..Na hoffentlich ist der dadurch entstehende Overhead nicht zu groß..



  • Spaghettimann schrieb:

    ..Na hoffentlich ist der dadurch entstehende Overhead nicht zu groß..

    Ich habe mich jetzt nicht schlau gemacht, aber ich vermute das Proxy Objekt kann implizit zu dem Typen konvertiert werden den man eigentlich per operator[] erwartet (lesen) und hat einen operator= zum schreiben. Jeder halbwegs anständige Compiler sollte die Funktionsaufrufe komplett wegoptimieren und so hat man wenig bis gar kein Overhead zur Laufzeit.


Anmelden zum Antworten