【问题标题】:Problem with a class setter function. Class setter function does not assign values properly类设置器函数的问题。类设置器函数未正确分配值
【发布时间】:2021-10-07 19:29:31
【问题描述】:

函数调用下面的语句没有被执行。我很茫然,为什么会这样?有人可以澄清一下。请考虑下面的代码:

#include<iostream>
#include<cmath>
using namespace std;
class Matrix
{
private:
int row,col;
double *values;
public:
    Matrix();
    Matrix(int r, int c, double* x);
void setdim(int m, int n){row=m;col=n;}
int getrowdim() const {return row;}
int getcoldim() const {return col;}
    void set_values(int i, double x);
    double get_value(int i) const;
friend Matrix operator+(const Matrix &A, const Matrix &B);
};
Matrix::Matrix()
{
    this->row = 0;
    this->col = 0;
    this->values = NULL;
}
Matrix::Matrix(int r, int c, double* x)
{
    this->row = r;
    this->col = c;
    this->values = new double[r*c];
    for (int i =0;i<r*c;i++)
    {
        cout<<"Enter value ["<<i<<"] ";
        cin>>this->values[i];
    }
}
void Matrix::set_values(int k, double x)
{
    this->values[k] = x;
}
Matrix operator+(const Matrix &A, const Matrix &B)
{
    int rowa = A.getrowdim();
    int cola = A.getcoldim();
    int rowb = B.getrowdim();
    int colb = B.getcoldim();
   
    if(rowa == rowb && cola == colb)
    {
        Matrix C;
        C.setdim(rowa, colb);
        for(int i =0; i< rowa*cola ; i++)
        {  
        cout<<"i = "<<i<<", A.get_value = "<<A.get_value(i)<<", B.get_value =  "<<B.get_value(i)<<endl;
        double m = A.get_value(i) + B.get_value(i);
        cout<<m<<endl;
        C.set_values(i, m );
        cout<<"Returned from C.set_values()"<<endl;

// THIS STATEMENT DOES NOT GET PRINTED. PLEASE TELL THE REASON // WHY. I SUSPECT THE ERROR IS HERE

        }
        return C;
    }
    else
    {
      cout<<"Invalid Operation";
      return A;
    }
}
double Matrix::get_value(int i) const
{
    return this->values[i];
}

int main()
{
    Matrix A(2,2,NULL);
    Matrix B(2,2,NULL);
    Matrix C;
    C = A+B;
    return 0;  
}

语句 - 从 C.set_values() 返回的语句根本不会被打印出来。

有人可以帮助澄清为什么会这样吗?非常感谢您的帮助!

【问题讨论】:

  • 不要使用原始的拥有指针作为成员。如果你这样做,你需要正确管理它。您的代码中还有更多问题。使用std::vector&lt;double&gt; values; 作为成员将解决其中的大部分问题
  • 您是否使用调试器单步执行函数以确定发生了什么?
  • setdim 设置了rowcol,但您仍然没有为coeff 分配任何内存。
  • @MathMan 默认构造函数将指针设置为NULL,但所有其他方法都希望它指向一个数组。那不仅“不好”,而且完全错误。更一般地说:类不遵守 3/5 规则,当类管理资源时这是强制性的
  • @MathMan 初学者经常想练习“手动方式”,但不幸的是,当一个人不了解 3/5 规则时,很容易出错。这有点像你第一次游泳时尝试穿越海洋(实际上你可以乘坐摩托艇;)

标签: c++ friend-function


【解决方案1】:

这里:

    Matrix C;                             // (1)
    C.setdim(rowa, colb);                 // (2)
    for(int i =0; i< rowa*cola ; i++)
    {  
    cout<<"i = "<<i<<", A.get_value = "<<A.get_value(i)<<", B.get_value =  "<<B.get_value(i)<<endl;
    double m = A.get_value(i) + B.get_value(i);
    cout<<m<<endl;
    C.set_values(i, m );                  // (3)

您默认构造一个Matrix (1)。默认构造函数只是将成员values 设置为NULL。然后在(2)中调整成员的大小,但values 仍然是NULL。然后,在 (3) 中调用 set_values 尝试访问数组元素,但没有数组。

问题是您的Matrix 有一个原始拥有指针作为成员。当班级管理资源时,您必须遵循rule of 3/5。如果你不这样做,班级就坏了。管理资源并非易事,遵循 3/5 规则只是最低要求。

您应该争取的更简单的替代方案是 0 规则。对于不管理资源的类,编译器生成的特殊成员恰到好处。如果您将原始指针成员替换为std::vector&lt;double&gt;,那么您无需担心复制、赋值或销毁,因为编译器会为您生成所需的方法。

【讨论】:

  • 很好的答案。我们大多数人开始时都没有考虑 3/5 规则!因为这就是通常的教学方式。但是,非常感谢您的洞察力
  • @MathMan 教授 C++ 本身就是一个话题。不幸的是,将 C++ 作为 C 类来教授,并使用 C++ 作为一种工具来教授指针而不是教授实际的 C++,这仍然是最先进的技术。顺便说一句,我绝不是 3/5 规则的专家。我的 99% 的类不需要任何特殊方法的自定义实现,另外 1% 是 RAII 类,它们有一个析构函数,但没有别的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-31
  • 1970-01-01
  • 2019-09-01
  • 2015-03-04
  • 2010-10-26
  • 2012-01-14
相关资源
最近更新 更多