自己的矩阵类乘法运算符

时间:2012-10-08 19:21:18

标签: c++ operator-overloading matrix-multiplication

我写了一个IntegerMatrix类来添加我自己的方法来处理矩阵。现在我写了这样一个函数:

IntegerMatrix** IntegerMatrix::multiplyMatrix(IntegerMatrix** table2)

(这是一个双指针,因为我拿着一大堆指向4x4 2D数组的指针。)所以我只能做到这一点:

matrix1.multplyMatrix(matrix2)

一个小问题是*没有为我自己的班级定义。所以我想重载这个操作符,我可以做这样的事情:

sum += this->table[i][k] * table2[k][j];

但是如何在重载运算符中获得正确的ik,其定义如下:

IntegerMatrix IntegerMatrix::operator*(const IntegerMatrix & k);

我现在唯一无法弄清楚的问题是如何获得正确的价值?

编辑:

我已经改写了这个,现在我有了:

IntegerMatrix IntegerMatrix::operator*(const IntegerMatrix & table2)
{
    int i, j, k;
    int sum;
    IntegerMatrix * result = new IntegerMatrix(SIZE);

    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            sum = 0;
            for (k = 0; k < SIZE; k++) {
                sum += this->table[i][k] * table2[k][j];
            }
            result[i][j] = sum;
        }
    }
    return *result;

}

这给了我一个[]:

的错误
Binary '[' : 'IntegerMatrix' does not define this operator or a conversiont o a type acceptable to the predefined operator.

3 个答案:

答案 0 :(得分:1)

我不明白你的问题,但这里是矩阵乘法规范如何工作的简短演示:

class IntegerMatrix {
    int table[3][3];

public:
      IntegerMatrix& operator*=(const IntegerMatrix& rhs) {
           //multiply table by rhs.table, store in data.
           return *this;
      }
};
IntegerMatrix operator*(IntegerMatrix lhs, const IntegerMatrix& rhs)
{return lhs*=rhs;} //lhs is a copy, so we can alter and return it

为你的编辑

你有代码

IntegerMatrix * result = new IntegerMatrix(SIZE); //pointer to an IntegerMatrix
...
result[i][j] = sum; //assign sum to the jth index of matrix # i

实际上,我认为你想要

result->table[i][j] = sum; //sum to the ixj index of the result matrix.

此外,您的功能是漏洞,因为您有new,但没有delete。这很容易在您的情况下修复,因为您不需要新的。 (你来自Java或C#背景吗?)

IntegerMatrix result(SIZE);
...
        result[i][j] = sum;
...
return result;

与上述所有内容无关,您实际上可能希望为整数矩阵提供[]运算符。

class row {
    int* data;
    int size;
public:
    row(int* d, int s) :data(d), size(s) {}
    int& operator[](int offset) {
        assert(offset<size);
        return data[offset];
    }
};

row operator[](int column) {
    assert(column<SIZE); 
    return row(table[column], SIZE);
}

这将允许你写:

IntegerMatrix result;
result[i][j] = sum;

答案 1 :(得分:1)

你可能会以Cargo-Cult programming的意义上传承一些文物。 : - /

例如:我猜你的multiplyMatrix原型上的双重间接(**)就在那里,因为你在某处看到了多维数组的整数...像:

void printMatrix(int ** myMatrix, int rows, int columns);

双重间接只是一个指向指针的指针。这是实现passing low-level C-style 2D arrays as parameters的具体实施点的一种方式。但是,如果您正在使用恰好代表Matrix的抽象类,那么这不是您必须要解决的问题。因此,一旦您将矩阵大小和数据本身封装在IntegerMatrix类中,您就不需要这样的东西:

void printMatrix(IntegerMatrix ** myMatrix);

更有可能你想传递一个简单的引用来封装数据的类,如下所示:

void printMatrix(IntegerMatrix const & myMatrix);

实际上你应该从乘法函数中返回一个新矩阵,至少如果你用它来实现一个运算符重载...因为语义上人们写a * b;之类的东西是没有意义的有修改一个。 (它可以,但你不应该。)所以你可以选择返回一个矩阵值实例:

IntegerMatrix IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);

...或返回指向新对象的指针:

IntegerMatrix * IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);

指针返回历来被许多库选择,因为从函数中的局部变量返回值将涉及在返回时制作副本。返回指针很快(它只“复制”一个32位/ 64位数字),同时复制对象的实例并且其中的大块数据很慢。因此,很多库只会在各处使用Matrix指针......问题是很难知道最终delete对象的责任。智能指针是确保这一点的一种方法:

unique_ptr<IntegerMatrix> IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);

但是C ++ 11有一些偷偷摸摸的能力,没有乱七八糟的速度。如果你从函数中返回值,并且编译器确定该值不会再次使用(因为它超出了范围),那么它可以像指针一样“移动”。这要求您支持RValue reference移动构造,并且存在各种各样的棘手问题。

真的有很多细微差别。如果你正在做这个教育练习,我建议你慢慢来,并通过一个教程,引导你完成每一步,而不是直接跳到火上。如果您在矩阵中使用低级C数组和动态分配,请将它们更改为std::vector std::vector

答案 2 :(得分:1)

对于一个IntegerMatrix对象,您使用this->table[i][k]来引用您保存矩阵数据的数组,而table2对象引用和{{1} }指针,您正在使用resulttable2[k][j]

我认为你想要做的是:

result[i][j]