98 votes

Opérateur[][] surcharge

Est-il possible de surcharger [] opérateur deux fois ? Pour permettre, quelque chose comme ça : function[3][3] (comme dans un tableau à deux dimensions).

Si cela est possible, j'aimerais voir un exemple de code.

27 votes

En fait, il est beaucoup plus simple et plus courant de surcharger operator()(int, int) au lieu de...

2 votes

Pourquoi recréer la roue ? Il suffit d'utiliser std::vector avec un constructeur de plage : stackoverflow.com/a/25405865/610351

0 votes

Ou vous pouvez simplement utiliser quelque chose comme using array2d = std::array<std::array<int, 3>, 3>;

125voto

Seth Carnegie Points 45196

Vous pouvez surcharger operator[] pour retourner un objet sur lequel vous pouvez utiliser operator[] encore une fois pour obtenir un résultat.

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;
};

Ensuite, vous pouvez l'utiliser comme :

ArrayOfArrays aoa;
aoa[3][5];

Il s'agit juste d'un exemple simple, vous voudrez ajouter un tas de vérifications de limites et autres, mais vous avez compris l'idée.

7 votes

Pourrait utiliser un destructeur. Et Proxy::operator[] devrait retourner int& pas seulement int

1 votes

Mieux vaut utiliser std::vector<std::vector<int>> pour éviter les fuites de mémoire et les comportements étranges lors de la copie.

0 votes

Les deux Boost's multi_array y extent_gen sont de bons exemples de cette technique. boost.org/doc/libs/1_57_0/libs/multi_array/doc/

22voto

Bo Persson Points 42821

Pour un tableau à deux dimensions, en particulier, vous pouvez vous contenter d'une seule surcharge operator[] qui renvoie un pointeur vers le premier élément de chaque ligne.

Vous pouvez ensuite utiliser l'opérateur d'indexation intégré pour accéder à chaque élément de la ligne.

4 votes

Il me semble que c'est la solution la plus pratique et la plus efficace. Je me demande pourquoi elle n'obtient pas plus de votes - peut-être parce qu'elle n'a pas le code qui attire l'attention.

21voto

Une expression x[y][z] exige que x[y] évalue un objet d qui soutient d[z] .

Cela signifie que x[y] doit être un objet avec un operator[] qui s'évalue en un "objet proxy" qui également soutient un operator[] .

C'est la seule façon de les enchaîner.

Alternativement, la surcharge operator() pour prendre plusieurs arguments, de sorte que vous pourriez invoquer myObject(x,y) .

0 votes

Pourquoi la surcharge des parenthèses permet-elle d'obtenir deux entrées alors que l'on ne peut pas faire de même avec les crochets ?

0 votes

@A.Frenzy Parce que : 1. une surcharge avec 2 paramètres entraînerait un appel à monObj[2,3], et non à monObj[2][3]. et 2. L'opérateur [] ne prend qu'un seul int, tandis que () prend un nombre quelconque de paramètres de n'importe quel type.

16voto

John Points 1342

C'est possible si vous renvoyez une sorte de classe proxy dans le premier appel []. Cependant, il existe une autre option : vous pouvez surcharger operator() qui peut accepter un nombre quelconque d'arguments ( function(3,3) ).

5voto

Node Points 2259

Vous pouvez utiliser un objet proxy, quelque chose comme ceci :

#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;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X