这个C++语法是什么意思,为什么它起作用?

gre*_*olf 15 c++ operator-overloading

我正在浏览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];
}
Run Code Online (Sandbox Code Playgroud)

输出:

x: 2.8
y: 4.2
z: 9.5
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?为什么这种语法有效?Point类不包含重载operator [],此处此代码试图自动转换为浮动某处.

我以前从未见过这种用法 - 至少可以说这看起来很奇怪而且令人惊讶.

谢谢

rlb*_*ond 17

p被隐式转换为a const float* const,指向x.所以*px,*(p+1)y等等.当然,以这种方式做这是一个非常奇怪的想法(并且令人困惑!).通常最好将x,y和z存储在一个数组中,并且如果他们真的想以这种方式做事,就可以获得整个数组的函数.

  • 更不用说这完全不安全了,因为`x`,`y`和`z`的内存位置没有明确定义. (19认同)
  • 另一个缺点是,如果你不小心使用Point作为布尔值,它会神秘地"工作"并且总是给出true,因为它强制Point - > pointer - > boolean (3认同)
  • @Jonathan Leffler:订单有保证,但不能保证`y`紧跟在`x`之后.无论出于何种原因,编译器都可以自由插入填充. (3认同)
  • @ D.Shawley:好点.虽然"合理的"编译器可能会这样做,但我不相信这种布局是标准的. (2认同)
  • @Jonathan Leffler,你是对的,它得到C++标准9.2/12的保证:"在没有插入访问说明符的情况下声明的(非联合)类的非静态数据成员被分配,以便后面的成员在一个类中有更高的地址宾语." (2认同)

Jer*_*fin 8

这里的想法是通过下标或名称来访问Point的成员.但是,如果你想这样做,你最好重载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");
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

这样,如果编译器在浮点数之间插入填充,它仍然可以工作 - 任何能够阅读C++的人都应该能够毫无问题地理解它.