8

私は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++で実装することはできますか?
可能であれば、コード内のクラスメソッドを変更するにはどうすればよいですか?

+2

クラスメソッドではありません。 – Kimi

答えて

9

メンバ関数はthis-pointerである左辺引数と一致します。ネイティブ型はメンバ関数を持つことができないため、非メンバ関数(および書き込みアクセス権を持たない他の型も含む)を介して、ユーザー定義型の右乗算を追加する必要があります。

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

あなたはそのために非メンバ関数が必要です:メンバーのオーバーロードは、常に左側にオブジェクトを取得しながら、

非メンバ演算子のオーバーロードは、あなたがいずれかの側のいずれかのタイプを指定することができ

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

関連する問題