Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+中的重载运算符+;使用模板类_C++_Class_Templates_Overloading_Operator Keyword - Fatal编程技术网

C++ C+中的重载运算符+;使用模板类

C++ C+中的重载运算符+;使用模板类,c++,class,templates,overloading,operator-keyword,C++,Class,Templates,Overloading,Operator Keyword,我有以下模板类: 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>

我有以下模板类:

    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;
};
模板
类矩阵{
公众:
矩阵(大小行、大小列、常量元素=0);
//标量乘法
矩阵运算符*(常数T和rhs){
矩阵结果(行、列);
对于(大小索引=0;索引<行*列;++索引){
结果.元素[索引]=元素[索引]*rhs;
}
返回结果;
}
矩阵运算符*(常数T和lhs、常数矩阵和rhs);
常量大小\u t行;
常量大小\u t列;
私人:
std::向量元素;
};
以及运算符的以下实现*:

// 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;
}
//标量乘法
模板
矩阵::运算符*(常数T和lhs、常数矩阵和rhs){
矩阵结果(rhs.行、rhs.列);
对于(大小索引=0;索引
当我试图编译时,clang说:
错误:重载的“operator*”必须是一元或二元运算符(有3个参数)|


我不太明白,我在这件事上遗漏了什么。一般来说,模板类在重载操作符时给我带来了困难,我不知道为什么。关于这个主题,这里有一些帖子,我尝试了一些代码的变体,但没有一个有效。

您正在声明
矩阵运算符*(const T&lhs,const Matrix&rhs)
作为成员函数,它有一个隐式参数
this
,这就是为什么编译器抱怨它“有3个参数”

你可以让它成为一个免费的模板函数

template <class T>
class Matrix {
    ...
    template <class Z>
    friend Matrix<Z> operator*(const Z& lhs, const Matrix<Z>& rhs);
    ...
};
模板
类矩阵{
...
模板
友元矩阵算子*(常数Z和lhs,常数矩阵和rhs);
...
};

//标量乘法
模板
矩阵运算符*(常数Z和lhs,常数矩阵和rhs){
矩阵结果(rhs.行、rhs.列);
对于(大小索引=0;索引
您的函数是成员函数。成员函数有一个隐藏参数,即this指针


您要么需要使运算符*成为非成员函数,要么需要去掉运算符*函数的一个参数(然后将“this”中的数据与传入矩阵中的数据相乘)

解决此问题的简单且合理有效的方法如下:

  • 首先实现
    矩阵和运算符*=(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
    运算符是为矩阵的每个模板实例自动生成的非模板内联非方法函数

    直接的问题是,非静态运算符除了两个显式参数外,实际上还接受了一个隐式
    this
    ,而二进制运算符不能接受3个参数


    复杂且更有效的解决方案涉及一种通常称为“表达式模板”的技术。缺点是表达式模板编写起来比较复杂,并且在
    auto
    关键字和类似情况下存在一些弱点

    例如:

    Matrix m = m1 * m2 + m3 * m4 + m5 + m6;
    
    表达式模板只需对矩阵的内部数据进行一次分配即可完成上述操作

    我的上述代码将复制
    m1
    ,将结果乘以
    m2
    。然后它将复制
    m3
    ,然后将其乘以
    m4
    。然后,它将把所有内容加起来,而不制作任何额外的副本。最后,此结果将移动到
    m

    因此,将创建两个矩阵,而不是表达式模板中的1


    一个更简单的解决方案(如OP的设计)将创建5个矩阵,而不是2个。

    作为成员函数,它将
    这个
    隐式地作为第一个参数,但您希望再添加2个。假设你有
    矩阵a,b,c你的操作符会被称为
    a.operator*(b,c)
    这有意义吗?否;)相关报道:我之前试过friend,但也没用@songyuanyao@kimsay我的错。修正。谢谢@songyuanyao。我是否只需要朋友来访问私人领域,或者还有更多吗?@kimsay仅用于访问私人领域,仅此而已。谢谢!很多时候,我不确定我应该在类定义内部还是外部实现一个函数。有一般规则吗?@kimsay如果它很短,并且您对
    inline
    及其危险没有意见,请在类定义中这样做。如果不是,把它放在别处?对于上述Koenig friend运算符,您必须在类定义中执行此操作(因为无法在类外引用运算符):这也意味着(对我来说)它们应该总是短的。而且friend仅用于访问私有字段?@kimsay nope:它可以做很多事情。它使ADL工作顺利,使操作符本身成为非模板(有一些很好的特性:模板操作符可能很脆弱),使它们成为非成员二进制操作符,等等。抱歉,明白了!谢谢!@牦牛
       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; }
    
    Matrix m = m1 * m2 + m3 * m4 + m5 + m6;