簡體   English   中英

使用模板類在C ++中重載運算符

[英]Overloading operators in C++ with template classes

我有以下模板類:

    template <class T>
class Matrix {

    public:
        Matrix(size_t rows, size_t columns, const T elements = 0);



        // scalar multiplication
        Matrix<T> operator*(const T& rhs){

            Matrix<T> result(rows, columns);

            for(size_t index = 0; index < rows * columns; ++index){
                result.elements[index] = elements[index] * rhs;
            }

            return result;
        }

        Matrix <T> operator*(const T& lhs, const Matrix<T>& rhs);



        const size_t rows;
        const size_t columns;


        private:

            std::vector<T> elements;
};

以及運營商*的以下實現:

// scalar multiplication
template <class T>
Matrix<T> Matrix<T>::operator*(const T& lhs, const Matrix<T>& rhs){

    Matrix<T> result(rhs.rows, rhs.columns);

    for(size_t index = 0; index < rhs.rows * rhs.columns; ++index){
        result.elements[index] = elements[index] * lhs;
    }
    return result;
}

當我嘗試編譯clang時說: error: overloaded 'operator*' must be a unary or binary operator (has 3 parameters)|

我不太明白,我在這里缺少什么。 一般來說,模板類在重載運算符方面給我帶來了困難,我不知道為什么。 關於這個主題的SO上有一些帖子,我嘗試了一些代碼的變化,但沒有一個工作。

解決此問題的簡單且合理有效的方法如下:

  1. 首先實現Matrix& operator *=(SomeType const&)和類似的操作。 這些是改變類的實例的變異操作,然后返回對*this的引用。

  2. *=形式實現內聯朋友的其他操作,其中lhs(通常)參數按值進行,修改並返回。

這往往非常簡單,並且通常比使用operator*而不是operator*=更有效。

所以你會有:

 template<class T, etc>
 struct Matrix{
   Matrix& operator*=(T const&);
   Matrix& operator*=(Matrix const&);
   Matrix& operator+=(Matrix const&);

你傳統上實現的。 然后:

   friend Matrix operator*(T const& t, Matrix m){ m*=t; return m; }
   friend Matrix operator*(Matrix m, T const& t){ m*=t; return m; }

   friend Matrix operator*(Matrix lhs, Matrix const& rhs){ lhs*=rhs; return lhs; }
   friend Matrix operator+(Matrix lhs, Matrix const& rhs){ lhs+=rhs; return lhs; }

現在你只需要實現一些傳統的方法。

這些friend運算符是非模板內聯非方法函數,它們是為Matrix的每個模板實例自動生成的。

立即解決問題是你非靜態的運營商實際上采取了一個隱含的this除了它的兩個明確的參數,和二元運算不能采取3個參數。


復雜且更有效的解決方案涉及一種通常稱為“表達模板”的技術。 缺點是表達式模板編寫起來比較復雜,並且在auto關鍵字和類似情況下有一些脆弱點。

舉個例子:

Matrix m = m1 * m2 + m3 * m4 + m5 + m6;

表達式模板將僅使用矩陣的內部數據的一個分配來執行上述操作。

我上面的代碼將復制m1 ,將結果乘以m2 然后它將復制m3 ,然后乘以m4 然后它會添加所有內容而不需要任何額外的副本。 最后,這個結果將被移到m

因此,在表達式模板的情況下,將創建兩個矩陣而不是1。

一個更天真的解決方案(如OP的設計)將創建5個矩陣而不是2個。

你要聲明Matrix <T> operator*(const T& lhs, const Matrix<T>& rhs); 作為成員函數,它有一個隱含參數this ,這就是為什么編譯器抱怨它“有3個參數”。

你可以使它成為一個免費的模板功能,

template <class T>
class Matrix {
    ...
    template <class Z>
    friend Matrix<Z> operator*(const Z& lhs, const Matrix<Z>& rhs);
    ...
};

// scalar multiplication
template <class Z>
Matrix<Z> operator*(const Z& lhs, const Matrix<Z>& rhs){

    Matrix<Z> result(rhs.rows, rhs.columns);

    for(size_t index = 0; index < rhs.rows * rhs.columns; ++index){
        result.elements[index] = elements[index] * lhs;
    }
    return result;
}

您的函數是成員函數。 成員函數有一個隱藏參數,this指針。

您需要使您的運算符*成為非成員函數,或者您需要刪除operator *函數的一個參數(然后將“this”中的數據與傳入Matrix <T>的數據相乘。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM