Привет, 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;
}
Указатели указывают на ячейку памяти, явно назначенную ей.
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);
Polynomial c = a + b;
Оператор присваивания должен возвращать ссылку на экземпляр, назначенный:
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
.
operator =
хорошо бы кодироваться как копирование / замена. (что после того, как copy-ctor фактически реализован, а это не так)
Начать с:
// 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;
Вот довольно чистка, с немного отличающейся функциональностью и улучшенным управлением памятью. Поскольку я не знал формат вашего входного файла, я пропустил чтение из части файла и просто использовал новый конструктор формы 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 для всех экспонентов выше, чем внутри многочлена.
operator+
не должен использоватьnew
. Это также не должно вызывать неконстантные аргументы.poly3
неинициализирован, поэтому*poly3
- неопределенное поведение.