2016-12-06 43 views
2

確定這樣的IM不知道如果我的理解是這樣 相關函子但問題是: 讓我們假設我有隔壁班:C++函數子使用,代碼重複避免

class Matrix{ 
public: 
    Matrix(int, int);      // constructor 
    Matrix(const Matrix&);     // copy constructor 

    Matrix& operator+= (const Matrix&); 
    Matrix& operator-= (const Matrix&); 
    int* operator[] (int) const; 

private: 
    int rows; 
    int cols; 
    int** Mat_p; 
}; 

和我想重載Matrix類中的+ =和 - =運算符。
現在,爲了總結或減去2個矩陣,我們需要遍歷兩個矩陣的每個值和增加或減少,因此會出現一些事情,如:

Matrix& Matrix::operator+= (const Matrix& M){ 
    for (int indexR = 0; indexR < rows; ++indexR) 
     for (int indexC = 0; indexC < cols; ++indexC) 
      Mat_p[indexR][indexC] += M[indexR][indexC]; 
} 

Matrix& Matrix::operator-= (const Matrix& M){ 
    for (int indexR = 0; indexR < rows; ++indexR) 
     for (int indexC = 0; indexC < cols; ++indexC) 
      Mat_p[indexR][indexC] -= M[indexR][indexC]; 
} 

,你可以看到無論是運營商「+ = 「和」 - =「具有相同的結構,所以所謂的」規則「之一就是避免代碼重複。
所以問的問題是我們如何避免這種重複並保持代碼有效?

+0

這少量的代碼重複是不是一個真正的問題imo – Brian

+0

@布萊恩那麼,我仍然想避免它(和任何方式,這只是一個例子...) –

回答

4

您可以實現單個模板化功能並向其中進行兩個調用。

template<typename T> 
Matrix& add_or_sub (const Matrix& M, const T &op){ 
    for (int indexR = 0; indexR < rows; ++indexR) 
     for (int indexC = 0; indexC < cols; ++indexC) 
      Mat_p[indexR][indexC] = op(Mat_p[indexR][indexC], M[indexR][indexC]); 
    return *this; 
} 

Matrix& Matrix::operator+= (const Matrix& M){ 
    return add_or_sub(M, std::plus()); 
} 

Matrix& Matrix::operator-= (const Matrix& M){ 
    return add_or_sub(M, std::minus()); 
} 
+2

4分鐘後...我有兩個音符雖然。我認爲最好命名'add_or_sub''piecewise_apply',因爲這就是它的作用。如果它是一個成員函數,它不應該返回'M'或'* this'嗎? – luk32

+0

@ luk32我剛剛從問題中複製了代碼,沒有注意到它缺少'return'。附: [命名很難](http://martinfowler.com/bliki/TwoHardThings.html)。 –

+0

@MarkRansom謝謝,非常感謝,讓我說我想添加另一個運算符重載,可以說* =或*(不帶賦值)與標量參數(int),意味着我想乘以標量int矩陣的每個節點。是否可以在給定的代碼中使用給定的模板實現? 在此先感謝。 –

2

我有點晚,但我想這個例子是比較完整的。我會建議編寫一個使用底層標量作爲操作數的分段仿函數應用程序,並返回相同類型,並實現使用此操作符的操作符。

一個例子:

#include <iostream> 
#include <functional> 
using namespace std; 

template <int Rows, int Cols, typename Scalar = int> 
class Matrix { 
    public: 
    void piecewise_apply(const Matrix& other, std::function<Scalar(Scalar,Scalar)> f) { 
     for (int indexR = 0; indexR < Rows; ++indexR) 
      for (int indexC = 0; indexC < Cols; ++indexC) 
       data[indexR][indexC] = f(data[indexR][indexC], other.data[indexR][indexC]); 
    } 

    Matrix<Rows,Cols,Scalar>& operator+=(const Matrix<Rows,Cols,Scalar>& rhs) { 
     piecewise_apply(rhs, std::plus<Scalar>()); 
     return *this; 
    } 

    Matrix<Rows,Cols,Scalar>& operator-=(const Matrix<Rows,Cols,Scalar>& rhs) { 
     piecewise_apply(rhs, std::minus<Scalar>()); 
     return *this; 
    } 
    private: 
    Scalar data[Rows][Cols]; 
}; 

int main() { 
    Matrix<5,5> a; 
    Matrix<5,5> b; 

    a.piecewise_apply(b, [](int a, int b){return a*b;}); 
    a -= b; 
    return 0; 
} 

的例子是不完整的,因爲它缺少初始化。 &rhs == this(優化的一個有趣的地方)也沒有保護,可能還有一些,但它顯示了這個想法。至於代碼效率..以及你應該依靠這個編譯器。

這種方法的一個優點是,即使它在默認版本中速度稍慢,您也可以嘗試編寫使用更復雜的優化技術(如阻塞或並行化等)的piecewise_apply,並在各個位置獲得加速。

對於一個簡單的版本,就像在你的例子中一樣,複製粘貼版本更短,更容易理解,因此可能是更好的選擇。

+0

不錯的答案,謝謝。 –