C++多项式(Polynomial)与有理数(Rational)类拷贝构造函数实现问题求助
看起来你遇到的核心问题是Polynomial类缺少正确的深拷贝机制,再加上几个语法和设计上的错误,导致Rational对象无法正确保存分子和分母的多项式数据。咱们一步步拆解问题并修复:
一、先解决最致命的语法和设计错误
1. 移除函数参数中的static关键字
C++里不能在函数参数前加static,这是语法错误。你的Polynomial构造函数声明里的static int deg完全不合法,必须去掉static:
// 错误写法 Polynomial(double * var = NULL, static int deg = NULL); Polynomial(static int deg ); // 修正后 Polynomial(double* var = nullptr, int deg = 0); Polynomial(int deg);
2. 把Polynomial的static int degree改成非静态成员
static成员是所有类对象共享的,这意味着你所有的Polynomial对象都会共用同一个degree值,完全不符合多项式的设计——每个多项式应该有自己的次数。所以要去掉static:
class Polynomial { private: double* variables; // 注:原拼写varibles改为variables更规范 int degree; // 去掉static! // ... 其他成员 };
二、修复拷贝问题:添加拷贝构造函数和赋值运算符
你的Rational构造函数里用this->numerator = p1;时,因为Polynomial没有自定义拷贝构造函数和赋值运算符,编译器会生成默认的浅拷贝版本。默认浅拷贝只会拷贝指针地址,而不是指针指向的数组内容,这会导致:
- 多个Polynomial对象共享同一块内存,修改其中一个会影响其他对象
- 析构时重复释放同一块内存导致崩溃
所以必须为Polynomial添加拷贝构造函数和赋值运算符重载:
// 拷贝构造函数 Polynomial::Polynomial(const Polynomial& other) { degree = other.degree; // 分配新内存并拷贝数据 variables = new double[degree]; for (int i = 0; i < degree; ++i) { variables[i] = other.variables[i]; } } // 赋值运算符重载(遵循RAII原则) Polynomial& Polynomial::operator=(const Polynomial& other) { if (this != &other) { // 防止自赋值 // 先释放当前对象的内存 delete[] variables; // 拷贝新数据 degree = other.degree; variables = new double[degree]; for (int i = 0; i < degree; ++i) { variables[i] = other.variables[i]; } } return *this; }
同时别忘了添加析构函数,避免内存泄漏:
Polynomial::~Polynomial() { delete[] variables; }
三、修复其他逻辑错误
1. 修正构造函数中的数组大小判断
你原来的构造函数里if (deg < (sizeof(var) / sizeof(double)))完全错误,因为var是指针,sizeof(var)得到的是指针的大小(比如64位系统是8字节),不是数组的实际大小。改成直接根据传入的deg分配内存:
Polynomial::Polynomial(double* var, int deg) : degree(deg) { variables = new double[degree]; if (var != nullptr) { // 拷贝传入的数组内容 for (int i = 0; i < degree; ++i) { variables[i] = var[i]; } } else { // 如果var为空,初始化全0 memset(variables, 0, degree * sizeof(double)); } } Polynomial::Polynomial(int deg) : degree(deg) { variables = new double[deg]; memset(variables, 0, deg * sizeof(double)); }
2. 修复setCoeff函数的无效操作
你的setCoeff里Polynomial(index);是创建了一个临时对象,不会修改当前对象的任何成员。正确逻辑是如果当前degree小于index,重新分配内存:
void Polynomial::setCoeff(int index, double num) { if (index >= degree) { // 重新分配更大的内存,拷贝原有数据 double* newVars = new double[index + 1]; memset(newVars, 0, (index + 1) * sizeof(double)); for (int i = 0; i < degree; ++i) { newVars[i] = variables[i]; } delete[] variables; variables = newVars; degree = index + 1; } variables[index] = num; }
3. 给Rational类添加print成员函数
你的测试代码里调用了r1.print()和r2.print(),但Rational类没有这个函数,需要补充:
class Rational { private: Polynomial numerator; Polynomial denominator; public: Rational(const Polynomial& p1, const Polynomial& p2); // 默认构造函数(适配测试代码里的Rational r1;) Rational() : numerator(0), denominator(1) {} void print() const { cout << "Rational: " << endl; cout << "Numerator: "; numerator.print(); cout << "Denominator: "; denominator.print(); cout << "-------------------------" << endl; } };
4. 修正Polynomial的print函数逻辑
原来的print函数里size = this->degree;然后while (this->variables[size] == 0)会导致数组越界(数组下标范围是0到degree-1),修正后:
void Polynomial::print() const { if (degree == 0 || (degree == 1 && variables[0] == 0)) { cout << "0"; return; } bool firstTerm = true; for (int i = degree - 1; i >= 0; --i) { if (variables[i] == 0) continue; if (!firstTerm) { cout << (variables[i] > 0 ? " + " : " - "); } else { firstTerm = false; if (variables[i] < 0) cout << "-"; } double absVal = abs(variables[i]); if (absVal != 1 || i == 0) { cout << absVal; } if (i > 0) { cout << "X"; if (i > 1) { cout << "^" << i; } } } cout << endl; }
四、修正后的测试代码
现在你的testRational函数可以正常工作,注意数组元素个数和degree的对应关系(比如6个元素对应degree=6,覆盖X0到X5):
void testRational() { Rational r1; r1.print(); double c[] = {0, 2, 2, 3, 4, 5}; Polynomial p1(c, 6); // 数组有6个元素,degree设为6 cout << "p1: "; p1.print(); c[0] = 1.2; Polynomial p2(c, 3); // 数组前3个元素,degree设为3 cout << "p2: "; p2.print(); Rational r2(p1, p2); cout << "\ntest8" << endl; r2.print(); }
总结
核心问题是缺少深拷贝机制,加上static成员和语法错误导致数据没有正确保存。修复这些问题后,Rational对象就能正确存储并打印分子和分母的多项式了。
内容的提问来源于stack exchange,提问作者user16375265

