C++索引类成员

use*_*395 3 c++

我有一个类向量

class vector3f
{
public:
float x;
float y;
float z;
};
Run Code Online (Sandbox Code Playgroud)

如果我想访问其中一个成员,我必须键入vec.x,vec.y和vec.z. 现在,我有一个应该按索引访问数据成员的算法,例如:

for(int i = 0; i < 3; i++)
{
vec[i] = i*i;
}
Run Code Online (Sandbox Code Playgroud)

没有索引这样做会导致几个if条件:

for(int i = 0; i < 3; i++)
{
if(i == 0){vec.x = i*i;}
else if(i == 1){vec.y = i*i;}
else if(i == 2){vec.z = i*i;}
}
Run Code Online (Sandbox Code Playgroud)

有没有办法索引数据成员,以便在编译时解决它们?我不想在vector类中使用数组,因为使用vec.x,vec.y和vec.z访问数据成员对程序员来说更方便.什么是避免这些if条件的最佳解决方案?

Rei*_*ica 5

您可以operator[]为您的类重载以将这些if条件(或最好是a switch)本地化为一个位置:

class vector3f
{
public:
  float x;
  float y;
  float z;

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

  float operator[] (size_t i) const
  { return (*const_cast<vector3f*>(this))[i];
}
Run Code Online (Sandbox Code Playgroud)

这是实现这一目标的通用和安全的方式.

如果您的类实际上是标准布局类1,如您所示,并且如果您知道编译器/平台的对齐和填充方案,并且如果您从这些知道floats将只是在内存中相继排列,您也可以像这样实现运算符:

float& operator[] (size_t i)
{
  return (&x)[i];
}
Run Code Online (Sandbox Code Playgroud)

这被视为x一个floats 数组的开头.它会更快,但依赖于我上面提到的ifs,并且不进行边界检查.


1这基本上意味着它没有非空基类,没有virtual函数,也没有非标准布局类型的数据成员.