Что означает этот синтаксис C ++ и почему он работает? - PullRequest
15 голосов
/ 03 сентября 2010

Я просматривал исходные тексты OpenDE и натолкнулся на странное использование синтаксиса оператора индексации массива '[]' в классе.Вот упрощенный пример, показывающий синтаксис:

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

Вывод:

x: 2.8
y: 4.2
z: 9.5

Что здесь происходит?Почему этот синтаксис работает?Класс Point не содержит перегруженных operator [], и здесь этот код пытается выполнить автоматическое преобразование, чтобы где-нибудь плавать.

Я никогда раньше не видел такого рода использования - это определенно выглядит необычно и удивительноменьше всего.

Спасибо

Ответы [ 3 ]

17 голосов
/ 03 сентября 2010

p неявно преобразуется в const float* const, что указывает на x. Итак, *p - это x, *(p+1) - это y и так далее. Конечно, довольно странная (и сбивающая с толку идея) сделать это таким образом. Обычно предпочтительнее хранить x, y и z в массиве и иметь функцию для получения всего массива, если они действительно хотят так поступить.

8 голосов
/ 03 сентября 2010

Идея в том, чтобы предоставить членам Точки доступ по подписке или по имени.Однако, если вы хотите сделать это, вам лучше перегрузить operator[] примерно так:

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

Таким образом, если компилятор вставляет отступ между числами, он все равно будет работатьи любой, кто умеет читать C ++, должен понимать это без проблем.

1 голос
/ 03 сентября 2010

Это просто способ обработки данных вашего члена как массива. Вы также можете сделать это с помощью структур. Это полезно, когда вы хотите удобочитаемость, но хотите иметь возможность перебирать простые структуры данных. Примером использования может быть объявление матрицы следующим образом:

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

Вы можете удобно ссылаться на каждую ячейку по имени, но вы также можете передавать указатель на m11 везде (и C будет видеть вашу структуру в виде массива, m11 - первый элемент) и выполнять итерацию по всем элементам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...