如何在c++中添加两个矩阵

How to add two matrices in c++

本文关键字:两个 c++ 添加      更新时间:2023-10-16

我写了一个类,但在添加矩阵时遇到了问题。我知道我必须重载operator+,但我不知道具体是怎么回事。有什么想法吗?

 class CMatrix
  {
    private:
            int Rows;
            int Columns;
            float* pData;
    public:
            CMatrix(void);
            CMatrix(int rows, int columns);               
            void setElement(int row, int column, float element);
            float getElement(int row, int column);
   ...};
    istream& operator>>(istream& in, CMatrix& matrix)
     {
in >> matrix.Rows;
in >> matrix.Columns;
for(int i = 0; i < matrix.Rows; i++)
    for(int j = 0; j < matrix.Columns; j++)
        in >> *(matrix.pData + i * matrix.Columns + j);
return in;
    }

      CMatrix::CMatrix(int rows, int columns)
    {
    Rows = rows;
    Columns = columns;
    pData = new float[Rows * Columns];
    float* pEnd = &pData[Rows * Columns];
    for(float* p = pData; p < pEnd; p++)
            *p = 0.0;
      } 
    void CMatrix::setElement(int row, int column, float element)
    {
     *(pData+  row * Columns + column) = element;
     }
    float CMatrix::getElement(int row, int column)
     {
       return *(pData + row * Columns + column);
      }

我重载了运算符的<lt;','>>',但我对operator+有问题。

不幸的是,我只有不到10个声誉。。。所以如果我写:

 CMatrix operator+(const CMatrix &lhs, const CMatrix &rhs)
    {
 Cmatrix result (Rows,Columns);
for(int i=0; i <Rows ; i++)
for( int j=0; j<Columns; j++)
 result.setElement(i,j)  = lhs.getElement(i,j) + rhs.getElement(i,j);   
return result;      
 }

 int main()
   {
const int n = 10, m = 5;
 CMatrix m1(n, m);
     CMatrix m2(n, m);
for(int i = 0; i < n; i++)
    for(int j = 0; j < m; j++)
        m1.setElement(i, j, (float)(i * m + j));
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
        m2.setElement(i, j, (float)(i * m + j));
    cout<<m1+m2;  // it doesn't work
   Thanks all for help, i did it at last...

除非您需要访问CMatrix的私有成员来执行计算,否则我建议您创建一个具有以下原型的非成员函数:

CMatrix operator+(const CMatrix &lhs, const CMatrix &rhs)
{
  // Do the work
  // You may need to throw exceptions based on incompatibilities between
  // matrix configurations (i.e., dimensions)
}

您还应该添加复制构造函数、析构函数和赋值运算符(可能还有移动构造函数和移动赋值),或者考虑禁用这些操作。如果不这样做,如果代码使用编译器提供的默认值,则会遇到严重问题。

您肯定需要添加一个析构函数,因为如果不添加,就会泄漏内存。

在C++中重载运算符的最佳方法是重载基于分段运算符(operator+=及其集合)的算术运算符(operator+operator-等)。

在您的情况下:

Matrix& operator+=(const Matrix& other)
{
    /* Add operation stuff... */
    return *this;
}
Matrix operator+(const Matrix& llhs , const Matrix& rhs)
{
    Matrix result( lhs ); //Copy of the first operand.
    result += rhs; //Add computation.
    return result; //NRVO-friendly implementation
}

这种实现有两个优点:

  • 可扩展性:+的实现基于+=。因此,运算符的行为是连贯的,并且是可管理的(没有重复的代码)
  • 高效:赋值运算符比二进制运算符更便于缓存(您使用同一个实例,使用两个实例并生成结果的实例),并且此实现仅使用一个副本(result的实例化中使用的显式副本),因为此代码旨在让编译器执行NRVO

高级主题:自动化运算符重载

您可以利用奇怪的递归模板模式来自动实现运算符重载。

什么是CRTP

CRTP是一个C++习惯用法,其中一个类从模板类继承,并将其作为模板自变量。例如:

template<typename T>
struct Base { /* ... */ };
struct Derived : public Base<Derived> { /* ... */ };

CRTP的关键是基类可以访问(知道)从它派生的类

操作员自动化:

在我们的例子中,我们可以使用对派生事例的访问来实现基类中的某个运算符,该运算符必须由派生类实现

让我举一个例子来解释这一点:不等式算子的实现是基于用户提供的等式算子的实现。

template<typename T>
struct EqualityHelper
{
    friend bool operator !=(const T& lhs , const T& rhs)
    {
        return !(lhs == rhs); //We use the operator== that T (The user class) implements.
    }
};

我们可以使用该CRTP基作为辅助类来实现从其继承的任何类的operator!=。例如:

class Foo : public EqualityHelper<Foo> //Magic!
{
    friend bool operator==(const Foo& lhs , const Foo& rhs)
    {
        /* Equality implementation */
    }
};
int main()
{
   Foo a,b;
   if( a != b) //Muahahahaha
   {
      /* ... */
   }
}

这可以扩展到任何操作员。比较运算符是展示这种方法威力的最好例子。整个比较运算符集可以基于其中一个来实现(a > bb < aa <= b!(a > b),等等):

template<typename T>
struct ComparisonHelper //Comparison operators based in operator> provided by the user
{
    friend bool operator<(const T& lhs , const T& rhs) { return rhs < lhs; }
    friend bool operator<=(const T& lhs , const T& rhs) { return !(lhs > rhs); }
    friend bool operator>=(const T& lhs , const T& rhs) { return !(lhs < rhs); } 
};

最后,我们可以利用多重继承同时使用多个助手:

//The complete set of logical comparison operators in six mantenible lines of code!
class Foo : public EqualityHelper<Foo> , public ComparisonHelper<Foo> 
{
   friend bool operator==(const Foo& lhs , const Foo& rhs)
   {
     /* Equality implementation */
   }
   friedn bool operator>(const Foo& lhs , const Foo& rhs)
   {
     /* Comparison implementation */
   }
}

Boost库有一个标头,其中包含一组使用此方法实现的助手:http://www.boost.org/doc/libs/1_54_0/libs/utility/operators.htm

我会简单地评论Michael Goldshteyn的帖子,但我想我没有足够的声誉来做这件事(哈哈),所以把这看作是对他的帖子的评论:

如果您需要+运算符来访问您的CMatrix类的私有数据(在这种情况下需要这样做),您可以通过插入以下行将此函数声明为您的CMetrix类中的朋友:

friend CMatrix operator+(const CMatrix &, const CMatrix &);

CMatrix类定义中的任何位置。这允许您在其他地方定义的重载运算符函数访问类的私有和受保护成员(如pData成员)。