我正在浏览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 []
,此处此代码试图自动转换为浮动某处。
我以前从未见过这种用法 - 至少可以说这看起来很不寻常和令人惊讶。
由于
答案 0 :(得分:17)
p
被隐式转换为const float* const
,指向x
。因此*p
为x
,*(p+1)
为y
,依此类推。
当然,以这种方式做这是一个非常奇怪的想法(并且令人困惑!)。通常最好将x,y和z存储在一个数组中,如果他们真的想以这种方式做事,就可以获得整个数组的函数。
答案 1 :(得分: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");
}
}
};
这样,如果编译器在浮点数之间插入填充,它仍然可以工作 - 任何能够阅读C ++的人都应该能够毫无问题地理解它。
答案 2 :(得分:1)
这只是将成员数据视为数组的一种方法。您也可以使用结构来执行此操作。当您想要可读性但希望能够迭代简单的数据结构时,这非常有用。一个示例用法是以这种方式声明矩阵:
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是第一个元素),并迭代所有元素。