我有3D矢量课程

class Vector3D{
    public: float x; float y; float z;
    //some functions, e.g. operator+ - * /
    //some 3D-specific function
};


和向量N-D类。

template<int constSize> class VecFloatFix{
    float database[constSize];
    //some functions, e.g. operator+ - * /
};


我注意到两个类之间存在代码重复,因此我认为我应该使Vector3D源自VecFloatFix<3>

class Vector3D : public VecFloatFix<3>{
    //some 3D-specific function
};


一切似乎都不错,只是直接有很多用户代码访问Vector3D::x,y,z

是否可以在不破坏用户代码的情况下从Vector3D派生VecFloatFix<3>

我最好的猜测是:

template<int constSize> class VecFloatFix{
    union{
        float database[constSize];
        float x,y,z;  ?????  sound like a hack
    }
    //some functions, e.g. operator+ - * /
};


编辑:将x,y,z硬编码为VecFloatFix是不可持续的。
如果我有一个从Vector2D派生的新类VecFloatFix<2>,则Vector2D::z可以正常编译(危险)。

最佳答案

这是一个仅公开大小为3的向量的xyz分量的版本。显然,其他大小也可能是专门的。

template<int constSize> struct VecFloatStorage
{
    float database[constSize];
};

template<> struct VecFloatStorage<3>
{
    union
    {
        float database[3];
        struct { float x, y, z; };
    };
};

template<int constSize> class VecFloatFix : public VecFloatStorage<constSize>
{
public:
    // Methods go here.
};


我不知道该标准是否保证struct { float x, y, z; }具有与float data[3]相同的内存布局,但是实际上我可以肯定这一假设成立。

GLM库使用了类似的技巧,只是它们根本没有数组成员,而是提供了返回(&this->x)[idx]的索引运算符。

10-08 11:54