为什么覆盖运算符不能使用指针?

Why override operators aren't working with pointer?

我需要用覆盖运算符 + - * = 编写一个 class 矩阵,我有一些代码可以工作,但有错误。

//Matrix.h

template <class T>
class Matrix
{
public:
    Matrix(int rows, int columns);
    Matrix(const Matrix<T> &m);
    Matrix<T>& operator=(Matrix<T>& m);
    Matrix<T> operator+(Matrix<T>& m) const;
    Matrix<T>* operator*(Matrix<T>* m);
};

template <class T> Matrix<T>& Matrix<T>::operator*(Matrix<T>& m) {  
    Matrix<T>* newMatrix = new Matrix<T>(rowCount, m.colCount);
    for (int i = 0; i < rowCount; ++i)
    {
        for (int j = 0; j < m.colCount; ++j)
        {
            newMatrix->data[i][j] = 0;
            for (int k = 0; k < colCount; ++k)
                newMatrix->data[i][j] += data[i][k] * m.data[k][j];
        }
    }
    return *newMatrix;
}

覆盖运算符在此代码中工作正常

Matrix<int> matrix(2, 2);
matrix = matrix + matrix;
//and other operators work fine here

但是这里编译时报错

Matrix<int>* matrix = new Matrix<int>(2, 2);
matrix = matrix + matrix;
matrix = matrix * matrix;
//etc

错误

error C2804: binary "operator +" has too many parameters

类型信息在 C++ 中很重要。

这个:

Matrix<int> matrix(2, 2);
matrix = matrix + matrix;

这里matrix的类型是Matrix。您已经为类型 Matrix 定义了 operator + ,所以这工作正常。


第二个不同:

Matrix<int>* matrix = new Matrix<int>(2, 2);
matrix = matrix + matrix;

这里matrix的类型是Matrix*。注意 Matrix 末尾的星号(这使它成为 Matrix Pointer)。这是与上面不同的类型。您尚未定义 operator +Matrix* 的作用,因此编译器会查看其默认操作并找到一些接近但不够准确的内容,并生成一条试图提供帮助的适当错误消息。

要使用上面定义的 operator +,您需要确保值的类型是 MatrixNOT Matrix*。您可以通过 operator *.

取消引用指针,将 Matrix* 转换为 Matrix
Matrix<int>* matrix = new Matrix<int>(2, 2);
(*matrix) = (*matrix) + (*matrix);

此处:(*matrix) 取消引用 Matrix* 对象,您会得到一个 Matrix。这现在可以正确地应用于您在上面定义的 operator +


但是说了这么多。
这解释了您的问题所在,但我认为您实际上不想(或不需要)在这种情况下使用 new

像这样动态分配内存可能不是实现它的正确方法。通常最好使用自动变量(因为这使内存管理更容易)。

template <class T>
Matrix<T> Matrix<T>::operator*(Matrix<T>& m)
// I also removed the & from the return value
// So that the value is copied out of the function.
// because with dynamic allocation the result will disappear
// after the function exits.
// Note: Though the matrix may be officially copied out
//       the compiler is likely to optimize away this copy.
//       and when you upgrade your class with move semantics
//       then it will definitely be moved.
{  
    Matrix<T> newMatrix(rowCount, m.colCount);
    // Remove the Pointer from the above line.
    // And fix the -> into . in the code below.


    for (int i = 0; i < rowCount; ++i)
    {
        for (int j = 0; j < m.colCount; ++j)
        {
            newMatrix.data[i][j] = 0;
            for (int k = 0; k < colCount; ++k)
                newMatrix.data[i][j] += data[i][k] * m.data[k][j];
        }
    }
    return newMatrix;
    // Now you can remove the * from the return value.
    // The code works exactly the same.
    // But you have not leaked the memory you allocated with `new`
}