9

我有一个Matrix类,它具有*用于标量和矩阵乘法的重载运算符。

template <class T> class Matrix
{
    public:
        // ...
        Matrix operator*(T scalar) const;
        // ...
}

// ...

template <class T>
Matrix<T> Matrix<T>::operator*(T RightScalar) const
{
    Matrix<T> ResultMatrix(m_unRowSize, m_unColSize);
    for (uint64_t i=0; i<m_unRowSize; i++)
    {
        for (uint64_t j=0; j<m_unColSize; j++)
        {
            ResultMatrix(i, j) = TheMatrix[m_unColSize * i + j] * RightScalar;
        }
    }
    return ResultMatrix;
}

// ...

我可以将矩阵对象与右侧的标量相乘,没有任何问题:

Matrix<double> X(3, 3, /* ... */);  // Define a 3x3 matrix and initialize its contents
Matrix<double> Y;                   // Define an output matrix
Y = X * 10.0;                       // Do the linear operation

但是,我如何以同样的方式从左侧乘以它?

Matrix<double> X(3, 3, /* ... */);
Matrix<double> Y;
Y = 10.0 * X;

在算术中,在进行乘法运算时,将常量写在左侧是一种常见的表示法。我想遵守这条规则以使我的代码更具可读性。

是否可以在 C++ 中实现这一点?
如果可能,如何修改代码中的类方法?

4

2 回答 2

12

成员函数由其左侧参数匹配,即 this 指针。由于本机类型不能具有成员函数,因此您必须通过非成员函数添加与用户定义类型的右乘法(以及您没有写入权限的其他类型)。

template<typename T>
Matrix<T> operator*(T const& scalar, Matrix<T> rhs)
{
    // scalar multiplication is commutative: s M = M s
    return rhs *= scalar; // calls rhs.operator*=(scalar);
}

注意:我上面写的非会员operator*是按照会员来实现的operator*=。建议将所有乘法编写为非成员函数,并使用成员operator*=通过 lhs 矩阵元素来实现这些乘法。

这将 a) 保持类接口最小,并且 b) 防止隐藏转换。例如,如果维度为 1x1,您可以有一个可以隐式转换为标量的 Matrix 类,如果您不提供直接匹配的单独重载,这些转换可能会静默发生。

template<typename T>
Matrix<T> operator*(Matrix<T> lhs, T const& scalar)
{
    return lhs *= scalar; // calls lhs.operator*=(scalar);
}

template<typename T>
Matrix<T> operator*(Matrix<T> lhs, Matrix<T> const& rhs)
{
    return lhs *= rhs; // calls lhs.operator*=(rhs);
}

请注意 lhs 矩阵如何是副本而不是参考。这允许编译器进行优化,例如复制省略/移动语义。另请注意,这些运算符的返回类型是Matrix<T>而不是const Matrix<T>某些旧 C++ 书籍中推荐的类型,但它阻止了 C++11 中的移动语义。

// class member 
template<typename T>
Matrix<T>& Matrix<T>::operator*=(Matrix<T> const& rhs)
{
    // your implementation
    return *this;
}

// class member 
template<typename T>
Matrix<T>& Matrix<T>::operator*=(T const& scalar)
{
    // your implementation
    return *this;
}
于 2013-01-23T14:48:41.313 回答
10

为此,您需要一个非成员函数:

template <typename T>
Matrix<T> operator*(T scalar, Matrix<T> const & matrix) {
    return matrix * scalar;
}

非成员运算符重载允许您在任一侧指定任何类型,而成员重载始终获取左侧的对象。

于 2013-01-23T14:47:20.083 回答