-1

我写了一堂课,我在添加矩阵时遇到了问题。我知道我必须重载运算符 +,但我不知道具体如何。有任何想法吗 ?

 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);
      }

我重载了运算符 '<<' ,'>>' ,但是运算符 + 有问题。

不幸的是,我的声望不到 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...
4

3 回答 3

6

除非您需要访问 的私有成员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)
}

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

你绝对需要添加一个析构函数,因为如果你不这样做,你会泄漏内存。

于 2013-08-07T16:27:39.727 回答
4

在 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

高级主题:自动操作符重载

您可以利用Curiously Recurrent Template Pattern来自动执行运算符重载。

什么是 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 > bis b < aa <= bis!(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

于 2013-08-07T16:40:25.217 回答
0

我只想对 Michael Goldshteyn 的帖子发表评论,但我想我没有足够的声誉来做到这一点(哈哈),所以考虑一下对他的帖子的评论:

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

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

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

于 2013-08-07T16:44:27.733 回答