[英]Inherited operator overloads not working on derived classes
我編寫了一些代碼,這些代碼設法混合了類模板,類繼承和運算符重載,但我不知道如何解決有關運算符使用的問題。 我有一個包含大量代碼的基類(尤其是運算符重載實現和數據持有者):
template <typename _type>
class baseMatrix {
public:
baseMatrix();
~baseMatrix();
//operators
baseMatrix<_type>& operator= (baseMatrix<_type> _mat);
template <typename _input_type> baseMatrix<_type>& operator*= (_input_type _val);
template <typename _input_type> baseMatrix<_type>& operator/= (_input_type _val);
template <typename _input_type> baseMatrix<_type>& operator+= (_input_type _val);
template <typename _input_type> baseMatrix<_type>& operator-= (_input_type _val);
template <typename _input_type> baseMatrix<_type>& operator*= (const baseMatrix<_input_type>& _mat);
template <typename _input_type> baseMatrix<_type>& operator/= (const baseMatrix<_input_type>& _mat);
template <typename _input_type> baseMatrix<_type>& operator+= (const baseMatrix<_input_type>& _mat);
template <typename _input_type> baseMatrix<_type>& operator-= (const baseMatrix<_input_type>& _mat);
protected:
std::vector<_type> data;
};
/* ... */
template <typename _type>
template <typename _input_type>
baseMatrix<_type>& baseMatrix<_type>::operator*=(_input_type _val) {
for (int i = 0; i < data.size(); ++i) data[i]*=_val;
return *this;
};
template <typename _type>
template <typename _input_type>
baseMatrix<_type>& baseMatrix<_type>::operator*=(const baseMatrix<_input_type>& _mat) {
for (int i = 0; i < data.size(); ++i) data[i]*=_mat.data[i];
return *this;
};
/* remaining operator overload functions */
我重載了標量和類參數的運算符。 然后,我還有一個額外的類matrix2D
,它從baseMatrix
繼承了這些運算符:
template <typename _type>
class matrix2D : public baseMatrix<_type> {
public:
matrix2D(int _rows, int _cols);
matrix2D(int _rows, int _cols, _type _val);
~matrix2D();
_type& operator()(int _r, int _c);
_type& at(int _r, int _c);
protected:
int nRows,nCols;
using baseMatrix<_type>::data;
};
但是,當實例化這些類時,我只能調用標量運算符,例如將*=
與兩個matrix2D
對象一起使用會導致編譯錯誤:
In file included from test.cpp:1:
baseMatrix.hpp: In instantiation of ‘baseMatrix<_type>& baseMatrix<_type>::operator*=(_input_type) [with _input_type = matrix2D<float>; _type = float]’:
test.cpp:29:6: required from here
baseMatrix.hpp:56:47: error: no match for ‘operator*=’ (operand types are ‘__gnu_cxx::__alloc_traits<std::allocator<float>, float>::value_type’ {aka ‘float’} and ‘matrix2D<float>’)
for (int i = 0; i < data.size(); ++i) data[i]*=_val;
另一方面,如果我實例化了baseMatrix
對象,則它會編譯OK(在運行時由於其他原因,即單元化數據失敗):
int main(int argc, char const *argv[]){
matrix2D<float> M1(5,5,0.0);
matrix2D<float> M2(3,3,6.0);
baseMatrix<float> testM;
M2*=0.47; // works
M2*=M1; // does not compile
M2*=testM // runtime error (segfault)
}
因此,顯然,運算符重載不適用於派生類,正確的語法是什么?
編輯:我已經意識到問題在於多個運算符重載。 由於某種原因,如果我只聲明運算符以將baseMatrix
對象作為參數,則可以編譯,反之亦然。
因此,對於M1*=M2
,過載解析檢查以查看operator*=(M1, M2)
和/或M1.operator*=(M2)
是否可能。 沒有適合非成員operator*=
候選人。 由於M1
類型為matrix2D<float>
,它繼承了baseMatrix<float>
,因此編譯器會看到M1
具有成員函數:
template <typename _input_type> baseMatrix<float>& operator*= (_input_type _val); // #1
template <typename _input_type> baseMatrix<float>& operator*= (const baseMatrix<_input_type>& _mat); // #2
下一步是嘗試推斷過載集中的每個模板的模板參數。 兩者都成功:對於模板#1,僅采用_input_type = matrix2D<float>
找到有效的專業化:
baseMatrix<float>& baseMatrix<float>::operator*=<matrix2D<float>>(matrix2D<float> _val); // #3
對於模板2,它通過使用M2
參數類型的基類並確定_input_type = float
來找到一種特殊化:
baseMatrix<float>& baseMatrix<float>::operator*=<float>(const baseMatrix<float>& _val); // #4
然后比較這些功能模板的專長。 這里的問題是您打算使用#4,但是#3被認為比#4更好,因為#3使用參數M2
的確切類型,但是#4需要派生到基數的轉換。 然后#3的實例包含語句data[i]*=_val;
對於data[i]
一個float
和_val
一個matrix2D<float>
,這沒有意義,從而導致錯誤。
一種解決方案是使用SFINAE技術確保模板#1不能與矩陣類型一起使用:
#include <utility>
#include <type_traits>
template <typename Type>
class baseMatrix {
private:
template <typename ValType>
static constexpr std::true_type is_matrix_ptr(const baseMatrix<ValType>*);
static constexpr std::false_type is_matrix_ptr(const void*);
public:
// ...
template <typename ScalarType,
std::enable_if_t<!decltype(is_matrix_ptr(std::declval<ScalarType*>()))
::value>* = nullptr>
baseMatrix& operator*=(ScalarType val);
// ...
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.