Перегрузка оператора указателями

0

Привет, c++ программисты. Я сталкиваюсь с проблемой, о которой я не могу понять. Я разделил следующую программу на соображения удобочитаемости и оставил то, с чем у меня возникают проблемы. Я пытаюсь перегрузить операторы + и =, но с динамически создаваемыми массивами. Правильные результаты дают методы + и = operator. Однако, когда я пытаюсь назначить результат из оператора + на * poly3, я получаю "* poly3 необходимо инициализировать" из компилятора. Если я инициализирую его, ему ничего не присваивается (я имею в виду результат из +). Мой вопрос, каков правильный способ сделать это. Мне нужен результат poly3 как динамический массив или указатель, поэтому я могу использовать его последним.

Большое спасибо за помощь заранее.

class Polynomial
{
    private:
        int *poly;
        int size;
    public:
        Polynomial();
        Polynomial(int);
        Polynomial(string,int);
        ~Polynomial();
        void setPoly(string);
        int *getPoly() const;
        Polynomial operator+(Polynomial&);
        void operator=(const Polynomial&);
};

Polynomial::Polynomial(string polyInput, int s) 
{
    size = s+1;

     poly = new int[size];
    //set all coef position to 0
    for(int i = 0; i < size; i++){
        *(poly + i) = 0;
    }
    setPoly(polyInput);
}

Polynomial Polynomial::operator+(Polynomial &polyRight)
{
    Polynomial *result = new Polynomial(size);

    for(int i = 0; i < size; i++)
        result->poly[i] = poly[i] + polyRight.poly[i];
    return *result;
}

void Polynomial::operator=(const Polynomial &polyRight)
{
    size = polyRight.size;
    for(int i = 0; i < size; i++){
        *(poly + i) = polyRight.poly[i];
    }
}

int main()
{
    int highestExp = 4;
    Polynomial *poly1;
    Polynomial *poly2;
    Polynomial *poly3;// = new Polynomial(highestExp); // for the result
    string input1,input2;



    ifstream inputFile("data.txt");

    getline(inputFile, input1);
    getline(inputFile, input2);

    poly1 = new Polynomial(input1,highestExp);
    poly2 = new Polynomial(input2,highestExp);

    *poly3 = *poly1 + *poly2;

    system("pause");
    return 0;
}
  • 1
    Ваш operator+ не должен использовать new . Это также не должно вызывать неконстантные аргументы.
  • 1
    poly3 неинициализирован, поэтому *poly3 - неопределенное поведение.
Показать ещё 2 комментария
Теги:

4 ответа

2
Лучший ответ

Указатели указывают на ячейку памяти, явно назначенную ей.

Ptr* pt = new Ptr();//pt points to a valid address in memory

Ptr* pt;//pt has not yet been initialized 

т.е. он не указывает на какой-либо действительный адрес. Использование pt может привести к неожиданному поведению. По умолчанию указатели должны указывать на NULL, и их нужно проверить для! NULL, а затем использовать.

В приведенном выше коде Polynomial * poly3; не указывает на какое-либо местоположение, и когда мы делаем * pol3, мы фактически разыскиваем местоположение, которое никогда не создавалось.

Когда вы выполняете Polynomial * poly3 = new Polynomial (highExp) ;, вы указываете poly3 на какое-то допустимое местоположение, и, следовательно, имеет смысл * pol3 = * poly1 + * pol2. Но будьте осторожны, когда вы делаете новое для poly3, вы создаете еще одно хранилище кучи, поэтому вам нужно убедиться, что вы освободите всю память, назначенную в кучу.

Лучшим решением было бы вернуть ваш opertor + верный указатель и сопоставить его с poly3 следующим образом:

Polynomial* Polynomial::operator+(Polynomial &polyRight)
{
  Polynomial *result = new Polynomial(size);

  for(int i = 0; i < size; i++)
    result->poly[i] = poly[i] + polyRight.poly[i];
  return result;
}

//и в основном

poly3 = (*poly1 + *poly2);
  • 2
    Кто будет убирать, если вы сделаете A = B + C + D?
  • 0
    Оператор + возвращает новый указатель - плохая идея. Помимо вызова утечек памяти, семантика странная: она не допускает Polynomial c = a + b;
Показать ещё 1 комментарий
3

Оператор присваивания должен возвращать ссылку на экземпляр, назначенный:

Polynomial& operator=(const Polynomial&);

В реализации вы должны return *this; , Вы также должны убедиться, что реализация надежна против назначения многочленов разного размера. В настоящее время это не так.

Затем, в main, poly3 не инициализируется. Просто опустите указатели и создайте все poly как автоматическое хранилище, локальные переменные в main():

Polynomial poly1(input1,highestExp);
Polynomial poly2(input2,highestExp);
Polynimial poly3 = poly1 + poly2;

В стороне, ваш operator+ имеет утечку памяти. Вы не должны использовать new int it. Создайте локальный Polynomial и верните его.

Кроме того, у вас нет деструктора, заботящегося о выпуске ресурсов, поэтому каждое создание Polynomial приводит к утечке памяти. У вашего класса слишком много обязанностей: управление ресурсами и многочлен. Вы должны позволить другому классу заботиться об управлении памятью. Используйте std::vector<int>, или, если это упражнение, напишите свой собственный класс с динамическим массивом и используйте его внутри Polynomial.

  • 2
    +1 Учитывая динамический характер многочлена, operator = хорошо бы кодироваться как копирование / замена. (что после того, как copy-ctor фактически реализован, а это не так)
2

Начать с:

                                             // allow adding const
const Polynomial Polynomial::operator+(const Polynomial &polyRight) const
{
    Polynomial result(size); // don't use a pointer

    for(int i = 0; i < size; i++)
        result.poly[i] = poly[i] + polyRight.poly[i];
    return result;
}

сделайте возврат const, чтобы избежать глупости (A+B)=C;

Polynomial&  Polynomial::operator=(const Polynomial &polyRight) // return a reference
{
    size = polyRight.size;
    for(int i = 0; i < size; i++){
        *(poly + i) = polyRight.poly[i];
    }
    return *this; // allow chaining
}

Обратите внимание, что как только вы исправите это, что вам нужно защитить от A = A в operator =():

if (this == &rhs)
{
     // do stuff
}
return *this;
1

Вот довольно чистка, с немного отличающейся функциональностью и улучшенным управлением памятью. Поскольку я не знал формат вашего входного файла, я пропустил чтение из части файла и просто использовал новый конструктор формы Polynomial(countOfExponents, x0, x1, x2, x3,..., xn)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <cstdarg>

using namespace std;


class Polynomial
{
    private:
        int *poly;
        int size;
    public:
        Polynomial() : size(0), poly(NULL) {}
        Polynomial(int size, ... );
        ~Polynomial() { delete[](poly); }

        void allocate(int size) { 
            if (NULL!=poly) {
                delete[](poly);
            }
            Polynomial::size = size; 
            poly=new int[size]; 
        }
        Polynomial operator+(const Polynomial&) const;
        Polynomial &operator=(const Polynomial&);
        int exponent(int p) const {
            return (p<size) ? poly[p] : 0;
        }
        string str() const;
};

Polynomial::Polynomial(int size, ...) : size(size) {
    va_list varargs;
    va_start(varargs, size);
    poly = new int[size];
    for (int i=0; i<size; i++) {
        poly[i] = va_arg(varargs, int);
    }
    va_end(varargs);
}

Polynomial Polynomial::operator+(const Polynomial &polyRight) const
{
    int newSize = max(size, polyRight.size);
    Polynomial result;
    result.allocate(newSize);

    for(int i = 0; i < newSize; i++)
        result.poly[i] = exponent(i) + polyRight.exponent(i);
    return result;
}

Polynomial &Polynomial::operator=(const Polynomial &polyRight)
{
    allocate(polyRight.size);
    memcpy(poly, polyRight.poly, sizeof(int) * size);
    return *this;
}

string Polynomial::str() const {
    stringstream out;
    for (int i=size-1; i>=0; i--) {
        out << poly[i];
        if (0<i) {
            out << "  ";
        }
    }
    return out.str();
}

int main()
{
    Polynomial one(3, 1, 2, 3);
    Polynomial two(3, 2, 3, 4);
    cout << one.str() << endl;
    cout << two.str() << endl;
    Polynomial three = one + two;
    cout << three.str() << endl;
    return 0;
}

Обратите внимание, что я также стараюсь не обращаться к памяти, которая может отсутствовать при работе с многочленами разных размеров. Доступ к poly [n] для полинома с менее чем n показателями может вызвать проблемы. Вместо этого используйте функцию экспоненты (n), которая вернет 0 для всех экспонентов выше, чем внутри многочлена.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню