[英]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上有一些帖子,我嘗試了一些代碼的變化,但沒有一個工作。
解決此問題的簡單且合理有效的方法如下:
首先實現Matrix& operator *=(SomeType const&)
和類似的操作。 這些是改變類的實例的變異操作,然后返回對*this
的引用。
以*=
形式實現內聯朋友的其他操作,其中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.