在结构中重载运算符() C++

C++ overloading operator() in struct

本文关键字:C++ 运算符 重载 结构      更新时间:2023-10-16

这是来自Box2d物理引擎的b2Math.h的代码。

struct b2Vec2
{   ...
/// Read from and indexed element.
float operator () (int i) const
{
return (&x)[i];
}
/// Write to an indexed element.
float operator () (int i)
{
return (&x)[i];
}
...
float x, y;
}

为什么我们不能只使用 SomeVector.x 和 SomeVector.y 来读/写矢量坐标?return (&x)[i];行实际上是如何工作的?我的意思是,在引用结构的 x 组件之后的数组制动器 [] 对我来说并不清楚。

提前感谢您的回复。

这是来自Box2d物理引擎的b2Math.h的代码。

您发布的 Box2D 源代码的复制和粘贴中似乎存在错误。特别是,在非常量方法中似乎缺少与号。

此外,此代码片段似乎来自当前发布的 2.3.2 代码库以外的代码库。

以下是GitHub上Box2D 2.3.2源代码的部分:

/// Read from and indexed element.
float32 operator () (int32 i) const
{
return (&x)[i];
}
/// Write to an indexed element.
float32& operator () (int32 i)
{
return (&x)[i];
}

为什么我们不能只使用 SomeVector.x 和 SomeVector.y 来读/写矢量坐标?

我们可以,而且我们通常这样做。

然而,Box2D(特别是b2AABB::RayCast)中的一些代码似乎是从算法编写的(b2AABB::RayCast的注释说"来自实时碰撞检测,p179"),该算法迭代x和y作为数组下标零和一。我猜Erin Cato(Box2D的作者)是这样实现这些运算符的:(a)使访问在风格上更符合算法,(b)使其工作,(c)使其以看起来有效的方式工作。我可以确认它至少有效。

我有自己的 Box2D 分支,其中我重写了这些运算符。我将其接口更改为使用[](而不是()),并将其实现更改为使用switch语句显式访问xy。后者我这样做是为了清楚地避免潜在的未定义行为,w.r.t. C++标准。

以下是我的实现的相关部分的片段(请注意,我甚至不声称这是完美的或好的,只是说它是一个有效的替代实现,并且它显然应该依赖于定义的行为):

/// Accesses element by index.
/// @param i Index (0 for x, 1 for y).
auto operator[] (size_type i) const
{
assert(i < max_size());
switch (i)
{
case 0: return x;
case 1: return y;
default: break;
}
return x;
}
/// Accesses element by index.
/// @param i Index (0 for x, 1 for y).
auto& operator[] (size_type i)
{
assert(i < max_size());
switch (i)
{
case 0: return x;
case 1: return y;
default: break;
}
return x;
}

行返回 (&x)[i]; 实际上是如何工作的?

正如我上面所暗示的,我之前已经研究过这个确切的问题。

当结构的 x 和 y 成员变量的内存布局与具有两个浮点数的数组相同时,它就会起作用;它通常这样做。所以与号 (&) 获取x参数的地址,然后将该地址视为数组开头的地址,然后按i进行索引。

我不认为这是定义的行为,但就C++标准而言。然而,对于我的口味来说,它的定义还不够明确。

希望这能回答你的问题。