C++ Operator [] überladen



  • scott meyer sagt in seinen büchern dazu, dass man den nicht kosntanten []-operator durch den konstanten implementieren soll, um sich die code verdopplung zu sparen aber trotzdem die const correctness zu wahren



  • Skym0sh0 schrieb:

    scott meyer sagt in seinen büchern dazu, dass man den nicht kosntanten []-operator durch den konstanten implementieren soll, um sich die code verdopplung zu sparen aber trotzdem die const correctness zu wahren

    Wie würde ich dann die Überladung aufrufen?
    Kann ich das überhaupt eindeutig machen? Eventuell könnte so doch eine Endlosschleife erzeugt werden? (je nach Compiler vermutlich)



  • ja kann man, nein keine endlosschleife (weil ist ja eindeutig xD).

    ich tippe hier einfach mal den orignalen code aus scott meyers "effektive c++ programmieren" ab, Tipp3, kapitel 1.3.2, seite 43 nach 3. auflage:

    class Textblock{
    public:
        ...
        const char& operator[](std::size_t position) const
        {
            ...
            ...
            ...
            return text[position];
        }
    
        char& operator[](std::size_t position)
        {
            return const_cast<char&>(static_cast<const Textblock&>(*this)[position]);
        }
    ...
    };
    


  • const char&
    

    Wieso zum Teufel eine Const-Referenz auf einen Basisdatentyp bei einem Rückgabewert?
    Dann doch einfach gleich eine Kopie...



  • Sone schrieb:

    const char&
    

    Wieso zum Teufel eine Const-Referenz auf einen Basisdatentyp bei einem Rückgabewert?
    Dann doch einfach gleich eine Kopie...

    Zum Beispiel weil man die Adresse des Elementes haben möchte.



  • wenn man ein einfaches beispiel machen will z.B.



  • Okay, danke. Auch wenn es krüppelig aussieht.



  • Sone schrieb:

    Wieso zum Teufel eine Const-Referenz auf einen Basisdatentyp bei einem Rückgabewert?
    Dann doch einfach gleich eine Kopie...

    Fail. 😃



  • TyRoXx schrieb:

    Sone schrieb:

    const char&
    

    Wieso zum Teufel eine Const-Referenz auf einen Basisdatentyp bei einem Rückgabewert?
    Dann doch einfach gleich eine Kopie...

    Zum Beispiel weil man die Adresse des Elementes haben möchte.

    Was zum Teufel willst du mit der Adresse einer konstanten Variable?



  • Sone schrieb:

    Was zum Teufel willst du mit der Adresse einer konstanten Variable?

    Ist doch ganz klar:

    (*(char*)(&lolwat[22])) = 'C';
    


  • theliquidwave schrieb:

    Sone schrieb:

    Was zum Teufel willst du mit der Adresse einer konstanten Variable?

    Ist doch ganz klar:

    (*(char*)(&lolwat[22])) = 'C';
    

    Ich hoffe das ist jetzt nicht dein Ernst.

    In einem konstanten Objekt sind auch alle Member (zumindest die, die nicht als mutual deklariert wurden) konstant.

    Und der Standard sagt

    any attempt to modify a const object during its lifetime (3.8) results in undefined behavior



  • ok, ich änders

    template<class T>
    class Foo {
    public:
        ...
        const T& operator[](std::size_t position) const
        {
            ...
            ...
            ...
            return vec[position];
        }
    
        T& operator[](std::size_t position)
        {
            return const_cast<T&>(static_cast<const Foo&>(*this)[position]);
        }
    ...
    };
    


  • Neh, ich will jetzt mal hören wieso das so viel Sinn macht. Von cooky seiner Majestät höchstpersönlich.



  • Sone schrieb:

    Von cooky seiner Majestät höchstpersönlich.

    bow down before her !



  • Sone schrieb:

    Ich hoffe das ist jetzt nicht dein Ernst.

    Gut bemerkt 😃


  • Mod

    Sone schrieb:

    Neh, ich will jetzt mal hören wieso das so viel Sinn macht. Von cooky seiner Majestät höchstpersönlich.

    Ich, der Kaiser des Universums, sage Euch, Sone, dass Ihr wieder mal mehr Mario Barth angucken solltet:

    void alte_c_funktion(const char* data, int N);
    
    vector<char> foo(500);
    // [...]
    alte_c_funktion(&foo[0], 500);
    

    Hat wohl jeder schon 1000 Mal gebraucht.



  • Sone schrieb:

    Neh, ich will jetzt mal hören wieso das so viel Sinn macht. Von cooky seiner Majestät höchstpersönlich.

    1. Konzeptuell modelliert ein vector, wie fast alles mit operator[], eine Art Arrayzugriff. In jedem fall möchte man mit [] auf ein Element selbst zugreifen - und das wird eben genau mit einer Referenz erreicht. Äquivalent steht dazu das Ziel von C++, Klassentypen als Built-In Typen zu behandeln. (Bei einem konstanten Array gibt es natürlich auch einen const&.) Eine konstante Referenz ist also nur konsistent mit dem Rest der Sprache.

    2. Praktisch gesehen willst du uU mal sowas:

    send(&v[5], xyz);
    

    Ja, man kann auch v.data() + 5 schreiben, aber da könnte man ja auch *(v.data() + 5) = 77 bei non-const schreiben. Der Punkt ist, dass das nicht das Verhalten ist, was man erwartet.



  • Sone schrieb:

    In einem konstanten Objekt sind auch alle Member (zumindest die, die nicht als mutual deklariert wurden) konstant.

    Und der Standard sagt

    any attempt to modify a const object during its lifetime (3.8) results in undefined behavior

    Mal abgesehen davon, dass keiner ernsthaft das machen will, was liquidwave scherzhafterweise geschrieben hat, bist du hier auf dem Holzweg; denn

    void ok(const char& ref)
    {
      const_cast<char&>(ref) = 'y';
    }
    
    int main()
    {
      char c = 'x';
      ok(c);
    }
    

    ist 100%ig legal, weil c kein "const object" ist. Nur weil du eine "Referenz auf const" oder "Zeiger auf const" hast, heißt das nicht, dass das referenzierte Objekt ein "const Objekt" ist. "Const Objekte" sind nur die, die schon mit einem const angelegt werden. Erst wenn du bei der Deklaration von c noch ein const davor schreibst, ist c ein "const object" und erst dann greift das, was du aus dem Standard zitiert hast. Bei einem vector<char> ist das sehr ähnlich. Die char-Objekte da drin sind keine "const objects".



  • . (s. u., hat sich geklärt)



  • Wo ist der Unterschied zwischen einem TextBlock und einem vector<char>?


Anmelden zum Antworten