Operator[][] Überlast

Lesezeit: 5 Minuten

Operator Uberlast
Eispopo

Kann man überladen [] Bediener zweimal? Zuzulassen, etwa so: function[3][3](wie in einem zweidimensionalen Array).

Wenn es möglich ist, würde ich gerne einen Beispielcode sehen.

  • Übrigens ist es viel einfacher und häufiger zu überladen operator()(int, int) stattdessen…

    – Invers

    14. August 2011 um 1:23 Uhr


  • Warum das Rad nachbauen? Benutz einfach std::vector mit einem Bereichskonstruktor: stackoverflow.com/a/25405865/610351

    – Geoffroy

    20. August 2014 um 13:22 Uhr

  • Oder Sie können einfach etwas wie verwenden using array2d = std::array<std::array<int, 3>, 3>;

    Benutzer4640261

    7. April 2020 um 2:05 Uhr

Operator Uberlast
Seth Carnegie

Sie können überladen operator[] um ein Objekt zurückzugeben, das Sie verwenden können operator[] nochmal um ein Ergebnis zu bekommen.

class ArrayOfArrays {
public:
    ArrayOfArrays() {
        _arrayofarrays = new int*[10];
        for(int i = 0; i < 10; ++i)
            _arrayofarrays[i] = new int[10];
    }

    class Proxy {
    public:
        Proxy(int* _array) : _array(_array) { }

        int operator[](int index) {
            return _array[index];
        }
    private:
        int* _array;
    };

    Proxy operator[](int index) {
        return Proxy(_arrayofarrays[index]);
    }

private:
    int** _arrayofarrays;
};

Dann können Sie es wie folgt verwenden:

ArrayOfArrays aoa;
aoa[3][5];

Dies ist nur ein einfaches Beispiel, Sie würden gerne eine Reihe von Begrenzungsprüfungen und so etwas hinzufügen, aber Sie verstehen die Idee.

  • könnte einen Destruktor verwenden. Und Proxy::operator[] sollte zurückkehren int& nicht nur int

    – Ryan Haining

    16. Dezember 2013 um 6:14 Uhr


  • Besser zu verwenden std::vector<std::vector<int>> um Speicherlecks und seltsames Verhalten beim Kopieren zu vermeiden.

    – Jarod42

    20. August 2014 um 12:35 Uhr

  • Beide Boosts multi_array und extent_gen sind gute Beispiele für diese Technik. boost.org/doc/libs/1_57_0/libs/multi_array/doc/…

    – alfC

    23. Januar 2015 um 22:06 Uhr

  • Aber, const ArrayOfArrays arr; arr[3][5] = 42; in der Lage sein, Kompilierung und Änderungen zu übergeben arr[3][5]was sich irgendwie von der Erwartung der Benutzer unterscheidet arr ist const.

    – abcdabcd987

    8. November 2015 um 12:45 Uhr

  • @ abcdabcd987 Das ist aus mehreren Gründen nicht richtig. Zuerst, Proxy::operator[] gibt in diesem Code keinen Verweis zurück (vorausgesetzt, Ihr Kommentar ist keine Antwort auf Ryan Haining). Noch wichtiger, wenn arr ist dann konstant operator[] kann nicht benutzt werden. Sie müssten eine konstante Version definieren, und natürlich würden Sie sie zurückgeben const Proxy. Dann Proxy selbst hätte konstante und nicht konstante Methoden. Und dann würde Ihr Beispiel immer noch nicht kompilieren, und der Programmierer wäre froh, dass im Universum alles in Ordnung ist. =)

    – Reisfeld

    5. April 2016 um 6:20 Uhr

Insbesondere für ein zweidimensionales Array könnten Sie mit einem einzigen Operator davonkommen[] -Überladung, die einen Zeiger auf das erste Element jeder Zeile zurückgibt.

Dann können Sie den integrierten Indizierungsoperator verwenden, um auf jedes Element innerhalb der Zeile zuzugreifen.

  • Sieht für mich nach der praktischsten und effizientesten Lösung aus. Frage mich, warum es nicht mehr Stimmen bekommt – vielleicht, weil es nicht den auffälligen Code hat.

    – Yigal Reiss

    26. April 2017 um 19:20 Uhr


Ein Ausdruck x[y][z] benötigt das x[y] wertet zu einem Objekt aus d das unterstützt d[z].

Dies bedeutet, dass x[y] sollte ein Objekt mit einem sein operator[] das wertet zu einem “Proxy-Objekt” aus Auch unterstützt ein operator[].

Nur so können sie verkettet werden.

Alternativ überladen operator() um mehrere Argumente zu nehmen, so dass Sie aufrufen könnten myObject(x,y).

  • Warum erlaubt die Überladung von Klammern, zwei Eingaben zu erhalten, aber Sie können das nicht mit den Klammern tun?

    – A. Raserei

    21. Mai 2020 um 22:49 Uhr


  • @A.Frenzy Weil: 1. das Überschreiben mit 2 Parametern zu einem Aufruf von myObj führen würde[2,3]nicht meinObj[2][3]. und 2. Die Anzahl der Parameter, die der Bediener übernimmt, kann nicht geändert werden [] operator akzeptiert nur einen int, während () eine beliebige Anzahl von Parametern beliebigen Typs akzeptiert.

    – Skorpion

    18. Dezember 2020 um 13:07 Uhr

Es ist möglich, wenn Sie zuerst eine Art Proxy-Klasse zurückgeben [] Anruf. Es gibt jedoch eine andere Option: Sie können operator() überladen, der eine beliebige Anzahl von Argumenten akzeptieren kann (function(3,3)).

Ein Ansatz ist die Verwendung std::pair<int,int>:

class Array2D
{
    int** m_p2dArray;
public:
    int operator[](const std::pair<int,int>& Index)
    {
       return m_p2dArray[Index.first][Index.second];
    }
};

int main()
{
    Array2D theArray;
    pair<int, int> theIndex(2,3);
    int nValue;
    nValue = theArray[theIndex];
}

Natürlich darfst du typedef der pair<int,int>

  • Dies wird viel attraktiver mit C++11 und geschweifter Initialisierung. Jetzt kannst du schreiben nValue = theArray[{2,3}];

    – Martin Bonner unterstützt Monika

    29. September 2016 um 16:51 Uhr

1647112209 225 Operator Uberlast
Knoten

Sie können ein Proxy-Objekt verwenden, etwa so:

#include <iostream>

struct Object
{
    struct Proxy
    {
        Object *mObj;
        int mI;

        Proxy(Object *obj, int i)
        : mObj(obj), mI(i)
        {
        }

        int operator[](int j)
        {
            return mI * j;
        }
    };

    Proxy operator[](int i)
    {
        return Proxy(this, i);
    }
};

int main()
{
    Object o;
    std::cout << o[2][3] << std::endl;
}

  • Dies wird viel attraktiver mit C++11 und geschweifter Initialisierung. Jetzt kannst du schreiben nValue = theArray[{2,3}];

    – Martin Bonner unterstützt Monika

    29. September 2016 um 16:51 Uhr

Es wäre toll, wenn du mir sagen könntest, was function, function[x] und function[x][y] sind. Aber lassen Sie mich es trotzdem als ein Objekt betrachten, das irgendwo deklariert ist

SomeClass function;

(Weil Sie gesagt haben, dass es sich um eine Operatorüberladung handelt, werden Sie sich wahrscheinlich nicht für Arrays interessieren SomeClass function[16][32];)

Damit function ist eine Instanz des Typs SomeClass. Dann schlagen Sie Erklärung von nach SomeClass für den Rückgabetyp von operator[] Überlastung, genau wie

ReturnType operator[](ParamType);

Dann function[x] wird den Typ haben ReturnType. Schau wieder nach oben ReturnType für die operator[] Überlast. Wenn es eine solche Methode gibt, könnten Sie dann den Ausdruck verwenden function[x][y].

Beachten Sie, anders function(x, y), function[x][y] sind 2 getrennte Anrufe. Daher ist es für Compiler oder Runtime schwierig, die Atomarität zu garantieren, es sei denn, Sie verwenden eine Sperre im Kontext. Ein ähnliches Beispiel ist, sagt libc printf ist atomar, während die überladenen nacheinander aufgerufen werden operator<< im Ausgabestrom sind es nicht. Eine Aussage wie

std::cout << "hello" << std::endl;

könnte ein Problem bei Multi-Thread-Anwendungen haben, aber so etwas wie

printf("%s%s", "hello", "\n");

ist gut.

994950cookie-checkOperator[][] Überlast

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy