重载索引运算符来模仿POD多维数组?

时间:2015-07-02 14:05:39

标签: c++ arrays operator-overloading

我有一个现有的类,其结构如下:

class Matrix
{
public:
    float Data[4][4];
    // ... methods
};

随后以下列方式使用:

Matrix m;
m.Data[0][0] = 1.0f;
float local = m.Data[0][0];
//...

我想用重载的索引操作符替换Data成员,因此我可以对使用的索引执行范围检查。虽然我可以更改Matrix类本身及其成员函数的实现,但我无法在现有代码中修改其用法,因此任何解决方案都要求使用语法保持相同。解决方案也不会改变sizeof(Matrix)。有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:3)

通常,对于这种情况,您需要使用代理类来处理第二个索引运算符。它看起来像这样,然后进入private课程的Matrix部分。我会忽略边界检查(你不应该自己添加它)。

class Proxy {
    Matrix& ref;
    size_t i;
public:
    Proxy(Matrix& on, size_t i) : ref(on), i(i) {}
    float operator[] (size_t j) {
        return ref.Data[i][j];
    }
};

然后让你的Matrix::operator[]返回此类的一个实例:

Proxy operator[] (size_t i) {
    return Proxy(*this, i);
}

注意,如果你想要一个const重载(即你想在const Matrix个对象上使用索引操作符),你需要一个单独的ConstProxy类,它有const Matrix& ref而不是{ {1}}但在其他方面是相同的。

还可以选择返回对数组的引用。 (注意:正如其中一条评论指出的那样,这对边界检查没什么帮助,但我觉得它很有意思,所以我将它留在这里。)

Matrix& ref

该语法相当神秘,我相信它在Visual Studio 2013中不起作用,但你可以使用typedef使其更清晰。

float (&operator[](size_t i))[4] {
    return Data[i];
}

如果您不介意放弃方括号索引,还有一个选择。您可以像这样重载函数调用操作符:

using Proxy = float[4];
Proxy& operator[](size_t i) {
    return Data[i];
}

答案 1 :(得分:1)

另一种方法是使用向量的语义定义代理类

 class Matrix
{
public:
    struct SubMatrix
    {
        class Vector
        {
        public:
            Vector(float *data) : Data(data) {}
            float &operator[](int index) { return Data[index]; }
        private:
            float *Data;
        };
        Vector operator[](int index)
        {
            return Vector(Data[index]);
        }
        float Data[4][4];
    };
    SubMatrix Data;
    // ... methods
};

然后你可以这样使用它:

Matrix m;
float f = m.Data[1][2];