Question Que signifie cette syntaxe C ++ et pourquoi fonctionne-t-elle?


Je regardais à travers la source de OpenDE et je suis tombé sur une utilisation de syntaxe wierd de l'opérateur d'indexation de tableau '[]' sur une classe. Voici un exemple simplifié pour afficher la syntaxe:

#include <iostream>

class Point
{
public:
    Point() : x(2.8), y(4.2), z(9.5) {}

    operator const float *() const
    {
        return &x;
    }

private:
    float x, y, z;
};

int main()
{
    Point p;
    std::cout << "x: " << p[0] << '\n'
              << "y: " << p[1] << '\n'
              << "z: " << p[2];
}

Sortie:

x: 2.8
y: 4.2
z: 9.5

Que se passe t-il ici? Pourquoi cette syntaxe fonctionne-t-elle? La classe Point ne contient pas de surcharge operator [] et ici ce code tente de faire une conversion automatique pour flotter quelque part.

Je n'ai jamais vu ce genre d'utilisation auparavant - ça a vraiment l'air inhabituel et surprenant pour le moins.

Merci


15
2017-09-03 02:44


origine


Réponses:


p est converti implicitement en un const float* const, qui pointe vers x. Alors *p est x, *(p+1) est y, etc. C'est une idée assez bizarre (et déroutante!) De le faire de cette façon, bien sûr. Il est généralement préférable de stocker x, y et z dans un tableau et d'avoir une fonction pour obtenir l'intégralité du tableau s'ils veulent vraiment faire les choses de cette façon.


17
2017-09-03 02:47



L'idée ici est de donner accès aux membres du Point en indice ou en nom. Si vous voulez faire cela, cependant, vous feriez mieux de surcharger operator[] quelque chose comme ça:

struct Point { 
    float x, y, z;

    float &operator[](size_t subscript) { 
        switch(subscript) {
            case 0: return x;
            case 1: return y;
            case 2: return z;
            default:  throw std::range_error("bad subscript");
        }
    }
};

De cette façon, si le compilateur insère un remplissage entre les flottants, cela fonctionnera toujours - et quiconque peut lire C ++ devrait pouvoir le comprendre sans aucun problème.


8
2017-09-03 03:13



Ceci est juste un moyen de traiter vos données membres en tant que tableau. Vous pouvez également le faire avec des structures. Ceci est utile lorsque vous voulez être lisible, mais que vous voulez pouvoir parcourir des structures de données simples. Un exemple d'utilisation serait de déclarer une matrice de cette manière:

typedef struct {
   CGFloat m11,m12,m13,m14;
   CGFloat m21,m22,m23,m24;
   CGFloat m31,m32,m33,m34;
   CGFloat m41,m42,m43,m44;
} CATransform3D;

Vous pouvez facilement référencer chaque cellule par son nom, mais vous pouvez également faire passer un pointeur à m11 partout (et C verra votre struct comme un tableau, m11 étant le premier élément), et itérer tous les éléments.


1
2017-09-03 03:01