【问题标题】:Overloaded operator C++: Object = Object * Object重载运算符 C++:Object = Object * Object
【发布时间】:2013-12-12 18:13:10
【问题描述】:

我在使用重载的 * 运算符乘以对象时遇到问题

在类中,我将运算符定义为:

const Matrix operator*(Matrix& B);

实现是

const Matrix Matrix::operator* (Matrix& B){
   Matrix r = Matrix(B.M,B.N);

   for(int i = 0; i < r.M; i++){
       for(int j = 0; j < r.N; j++){
        r.data[i*N+j] = (*this)(i,j) * (int)B(i,j);
       }
   }
   return r;
}

当我打电话时

 Matrix C = A * B

我会得到预期的结果,但是调用

C = C * C

导致错误。

我猜它与调用对象 C 相关,但我不确定该怎么做!

编辑:

我的赋值运算符。矩阵 R 是深拷贝。

Matrix Matrix::operator=(Matrix& B){
Matrix r(M,N);

for(int i = 0; i < M; i++){
    for(int j = 0; j < N; j++){
        r.data[i*N+j] = B(i,j);                                 
    }
}
return r;

}

【问题讨论】:

  • 什么样的错误?编译时还是运行时?如果它是运行时的,它会崩溃,还是只会给出不正确的结果?
  • 我建议将函数签名更改为Matrix Matrix::operator* (Matrix const&amp; B) const
  • 只有方阵可以自身相乘
  • 这是我的朋友。假设 C 是 5x5。
  • @Billy Jake O'Connor:你对Matrix 类的复制赋值运算符做了什么?您的错误在那里,而不是在您发布的内容中。

标签: c++ object overloading operator-keyword


【解决方案1】:

错误是因为您将数据存储在一个名为“data”的变量中(它是堆上的一个 int[]),并且您没有覆盖您的赋值运算符以将值从被复制的对象复制到当前成员变量“数据”。因此,默认赋值运算符将为您复制“数据”指针,在您的情况下,该指针来自分配后超出范围的临时值。您的析构函数很可能会删除您现在指向的“数据”变量,因为临时变量超出了范围。

您已经定义了自己的复制构造函数来在堆上建立“数据”变量。第一个示例,其中 Matrix C = A * B 将使用该复制构造函数,该构造函数有效。

第二个例子使用了默认的赋值操作符,它只会从操作返回的临时值中复制数据指针。因此,您基本上没有数据指向的价值。

您必须定义一个赋值运算符才能完成这项工作。

以下是与您的复制构造函数一起使用的建议函数:

void Matrix::swap(Matrix& other)
{
   std::swap(M, other.M);
   std::swap(N, other.N);
   std::swap(data, other.data);
}

Matrix& Matrix::operator= (Matrix matrix)
{
   swap(matrix);
   return *this;
}

Matrix Matrix::operator* (const Matrix& B)
{
   Matrix r = Matrix(B.M,B.N);

   for(int i = 0; i < r.M; i++){
       for(int j = 0; j < r.N; j++){
        r.data[i*N+j] = (*this)(i,j) * (int)B(i,j);
       }
   }
   return r;
}

这很好用,因为复制构造函数将用于赋值运算符 (operator=) 中的“矩阵”。然后,交换函数会将“数据”数组与 Matrix 的临时副本进行交换。因此,您将从操作*的临时变量中复制适当的“数据”。

【讨论】:

    【解决方案2】:

    这与“调用对象C”无关。

    第一个版本

    Matrix C = A * B;
    

    使用构造函数Matrix类来初始化新对象C

    第二版

    C = C * C;
    

    使用 Matrix 类的 assignment 运算符为现有对象 C 分配新值。

    您设法以某种方式搞砸了赋值运算符的声明/实现(您没有在您发布的代码中显示),这就是第二个版本无法编译的原因。

    您的operator * 声明也存在问题。即使您想将其作为类成员,更有意义的声明方式是

    Matrix Matrix::operator* (const Matrix& B) const {
      ...
    

    注意const 限定符的放置方式。

    编辑:所以,这是你的问题。你的赋值运算符完全坏了。

    首先,您将赋值运算符声明为

    Matrix Matrix::operator=(Matrix& B)
    

    此运算符不能接受右侧的临时对象,因为您未能将参数声明为const。非常量引用不能绑定到临时对象。而在C = C * C 中,赋值的右侧实际上是由*operator 生成的临时对象。

    将赋值运算符重新声明为

    Matrix &Matrix::operator=(const Matrix& B)
    

    注意,它接受const 引用并返回一个引用。

    其次,您的赋值运算符应该分配给*this,而不是一些独立的临时对象。它应该返回对*this 的引用。换句话说,实现应该类似于

    Matrix &Matrix::operator=(const Matrix& B){
    
      // Resize `*this` to match the size of `B`
    
      for(int i = 0; i < M; i++){
        for(int j = 0; j < N; j++){
            this->data[i*N+j] = B(i,j);                                 
        }
      }
      return r;
    }
    

    【讨论】:

    • 如果方法是const,它如何创建一个新矩阵?还是修改现有的?
    • @Billy Jake O'Connor:这不是“赋值运算符”。您发布的是一个复制构造函数。它与赋值运算符完全无关。您的问题出在 赋值运算符 中。 拷贝构造函数赋值运算符的区别你明白吗???赋值运算符称为operator =。你对它做了什么?
    • @Smac89:您认为在const 方法中创建新矩阵有什么问题? const 方法只会阻止您修改 *this 而不会阻止其他任何事情。 OP在operator *中没有修改(也不需要修改)*this,所以声明方法const是完全合乎逻辑的。
    • 好的,我对 C++ 完全陌生,我已经把它全部塞进去了。我认为复制构造函数可以代替赋值运算符。为什么 = 运算符不能简单地将 C * C 的值复制到 C 中?还是我需要明确告诉它如何处理?
    • @Billy Jake O'Connor:您是否声明了自己的operator =?是的,您确实需要声明自己的 operator = 并且您必须正确地执行此操作(即也在那里进行深层复制)。在继续之前搜索并阅读“三法则”
    【解决方案3】:

    尝试像这样定义运算符:

    Matrix operator* (const Matrix& x, const Matrix& y)
    {
        //...
    }
    

    【讨论】:

    • 这不是 * 运算符好友。原来是赋值运算符。不过还是谢谢。
    猜你喜欢
    • 1970-01-01
    • 2012-11-17
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    相关资源
    最近更新 更多