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*=してlhsMatrix要素でこれらの乗算を実装することをお勧めします。

これにより、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マトリックスがコピーであり、参照ではないことに注意してください。これにより、コンパイラーはコピーの省略/移動セマンティクスなどの最適化を行うことができます。また、これらの演算子の戻り型は、一部の古いC ++ブックでは推奨されてMatrix<T>いませんが、C++11での移動セマンティクスを妨げることに注意してください。const Matrix<T>

// 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 に答える