


Вопрос по c++ (перегрузка оператора)
Здравствуйте. Делаю класс для работы с многочленами, пытаюсь перегрузить оператор сложения. Ниже код с комментариями (main и метод для печати убрал, так как слишком много букв). На скрине вывод и всплывающее окно. Иногда их несколько друг за другом, но чаще всего одно. Все кроме перегрузки работает корректно. Мне нужно перегрузить и другие операторы, но там я думаю проблемы будут схожие. Возможно ошибка какая-то глупая, я только учусь писать на плюсах и первый раз перегружаю оператор. Буду благодарен если поможете разобраться.
#include <iostream>
#include <locale.h>
#include <cmath>
class Polynomial
{
private:
int order; // Порядок многочлена
double* coefficients; // Указатель на массив коэффициентов
public:
// Конструктор класса для создания многочлена заданного порядка
Polynomial(int order)
{
this->order = order;
this->coefficients = new double[order + 1];
for (int i = 0; i <= order; i++) {
this->coefficients[i] = 0.0; // Инициализируем коэффициенты нулями
}
}
// Деструктор для освобождения выделенной памяти
~Polynomial()
{
delete[] coefficients;
}
// Метод для установки коэффициента при заданной степени
void setCoefficient(int power, double value)
{
if (power >= 0 && power <= order)
{
coefficients[power] = value;
}
else
{
std::cerr << "Недопустимая степень многочлена" << std::endl;
}
}
// Метод для получения коэффициента при заданной степени
double getCoefficient(int power) const
{
if (power >= 0 && power <= order) {
return coefficients[power];
}
else {
std::cerr << "Недопустимая степень многочлена" << std::endl;
return 0.0; // Возвращаем 0 в случае ошибки
}
}
// Метод для вычисления значения многочлена для заданного аргумента x
double evaluate(double x) const
{
double result = 0.0;
for (int i = 0; i <= order; i++)
{
result += coefficients[i] * pow(x, i);
}
return result;
}
Polynomial operator+(const Polynomial& other) const
{
int maxOrder = std::max(order, other.order); // Максимальный порядок многочлена
int minOrder = std::min(order, other.order);
Polynomial result(maxOrder); // Создаем новый многочлен с максимальным порядком
for (int i = 0; i <= minOrder; i++)
{
result.setCoefficient(i, getCoefficient(i) + other.getCoefficient(i));
}
return(result);
}
};

В своём классе ты взял на себя управление памятью массива коэффициентов. Значит, ты должен перекрыть все точки, где указатель на этот массив должен быть скопирован или удалён, в том числе:
Конструктор копирования
Оператор присваивания
Твой оператор + возвращает копию объекта, оригинал - временный объект - уничтожается, и в копии остаётся указатель на невалидную память.
Но здесь нужно сделать шаг назад и пересмотреть решение управлять памятью внутри прикладного класса. Т.к. если ты будешь так делать, у тебя весь код превратится в затыкание дыр и в компромиссы между утечками и невалидными указателями, как это происходит в ламерских приложениях чудо-"специалистов" вроде двух отметившихся выше.
Какие есть варианты переложить управление памятью на рантайм языка:
Самый простой - используй std::vector вместо указателя. Минус здесь лишь в том, что все коэффициенты будут копироваться каждый раз при копировании полинома. Но если их немного (скажем, до 10-й степени), то это можно принять. Ну, и хранение пары лишних указателей тоже входит в накладные расходы ("под капотом" вектор представляет собой три указателя, впрочем, взамен ты сможешь избавиться от переменной order, заменив её на vector::size()).
Вариант посложнее - использовать std::shared_ptr, чтобы разные полиномы могли ссылаться на один массив коэффициентов. А при изменении значения коэффициента делать отдельную копию массива для данного полинома, если счётчик ссылок больше 1.
Если полином не копируется по логике приложения (т.е. возможны только технические короткоживующие копии), то можно завести std::auto_ptr. При копировании он обнуляет указатель у auto_ptr источника. Здесь придётся аккуратно отслеживать время жизни твоих полиномов, чтобы ты не обращался к коэффициентам полинома-источника после его копирования.
Если задача учебная, то бери вариант 1 и не парься.
2 и 3 - это для промышленных применений.
Попробуйте что-нибудь полезного для себя сделать из этого...
https://pastebin.com/BV4GD8eb
#include <iostream>
class Polynomial {
public:
int order;
double* coefficients;
Polynomial(int order) : order(order), coefficients(new double[order + 1]) {
for (int i = 0; i <= order; i++) {
coefficients[i] = 0.0;
}
}
~Polynomial() {
delete[] coefficients;
}
Polynomial operator+(const Polynomial& other) const {
int maxOrder = std::max(order, other.order);
Polynomial result(maxOrder);
for (int i = 0; i <= maxOrder; i++) {
result.coefficients[i] = (i <= order ? coefficients[i] : 0.0) + (i <= other.order ? other.coefficients[i] : 0.0);
}
return result;
}
};
int main() {
Polynomial p1(3);
p1.coefficients[0] = 1;
p1.coefficients[1] = -2;
p1.coefficients[2] = 3;
p1.coefficients[3] = -4;
Polynomial p2(3);
p2.coefficients[0] = 2;
p2.coefficients[1] = -1;
p2.coefficients[2] = 2;
p2.coefficients[3] = 2;
Polynomial p3 = p1 + p2;
std::cout << "p1 + p2: ";
for (int i = 0; i <= p3.order; i++) {
std::cout << p3.coefficients[i] << "x^" << i;
if (i < p3.order) {
std::cout << " + ";
}
}
std::cout << std::endl;
return 0;
}
p1 + p2: 3x^0 + -3x^1 + 5x^2 + -2x^3
может минус 1
this->coefficients = new double[order + 1];
Polynomial operator+(const Polynomial& other) const
{
int maxOrder = std::max(order, other.order); // Максимальный порядок многочлена
int minOrder = std::min(order, other.order);
Polynomial result(maxOrder); // Создаем новый многочлен с максимальным порядком
for (int i = 0; i <= minOrder; i++)
{
result.setCoefficient(i, getCoefficient(i) + other.getCoefficient(i));
}
// Копируем оставшиеся коэффициенты из большего многочлена
if (order > other.order)
{
for (int i = minOrder + 1; i <= maxOrder; i++)
{
result.setCoefficient(i, getCoefficient(i));
}
}
else if (order < other.order)
{
for (int i = minOrder + 1; i <= maxOrder; i++)
{
result.setCoefficient(i, other.getCoefficient(i));
}
}
return std::move(result); // Возвращаем ссылку на объект result
}