powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Меняются поля класса, хотя и не должны
25 сообщений из 25, страница 1 из 1
Меняются поля класса, хотя и не должны
    #33812951
Opus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеется простенький класс описывающий полином (хедер и реализация - в аттаче). Устроен просто: поле power хранит степень полинома, массив koefs хранит коеффициенты (от младшей степени - 0 - к старшей), плюс имеется несколько перегруженных операторов.
Написал малюсенькую прожку, текстирующую это дело:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
#include <iostream.h>
#include "Polynom.h"

int main(void)
{
	cout << "Polynom testing application\n";
	double k1[] = { 1 ,  2 ,  3 };
	double k2[] =  { 1 ,  2 };
	Polynom p1( 2 , k1), p2( 1 , k2);
	
	
	Polynom p11 = - p1;
	cout << p11 << '\n';
	
	cout << "Polynoms: " << p1 << ", " << p2 << '\n';
	
	Polynom p4 = p1 - p2;
	cout << "Subtract: " << p4 << '\n';
	cout << "Polynoms: " << p1 << ", " << p2 << '\n';
	
	Polynom p5 = p1 * p2;
	cout << "Multi: " << p5 << '\n';
	cout << "Polynoms: " << p1 << ", " << p2 << '\n';
	
	Polynom p3 = p1 + p2;
	cout << "Sum:" << p3 << '\n';
	cout << "Polynoms: " << p1 << ", " << p2 << '\n';
	
	return  0 ;
};
Проблема в том, что после строчки Polynom p4 = p1 - p2 поле koefs у p2 непонятным образом меняется (на противоположные значения). Усугубляется проблема тем, что отладчик (пишется в MinGW Developer Studio) на этой строке виснет. Теперь сижу и не могу понять, что же тут не так - подскажите, плз :)
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813150
Фотография Lelikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На гуще не гадаем ))

Покажите-ка код класса.
________________________________________________________
Глюк - это высокоорганизованная система не поддающихся определению частиц
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813225
muk07
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то я не увидел в классе оператора =
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813236
Opus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LelikkНа гуще не гадаем ))

Покажите-ка код класса.
Дык приложен в аттаче к моему первому посту..
muk07Что-то я не увидел в классе оператора =
А нужен? И на что должен быть в таком случае похож?
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813241
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OpusИмеется простенький класс описывающий полином
Хм. Может быть, я уже совсем забыл C++, но имхо проблема в том, что Вы вовсю возвращаете локальные объекты. Я не помню, как ведет себя компилятор в этом случае, но в принципе у него два выхода: либо таки вернуть указатель на мусор в стеке, либо вернуть копию локального объекта; подозреваю, он идет вторым путем. Тогда встает вопрос - как он делает копию. В отсутствие конструктора копирования (а либо я слеп, либо его не вижу) компилятор, сколь помнится, добавляет дефолтовый конструктор побайтового копирования. Этот конструктор, будучи вызванным, старательно откопирует Ваш указатель на массив коэффициентов; operator- воспользуется этим указателем и инвертирует коэффициенты, что приведет к неожиданному изменению во всех полиномах, ссылающихся на этот откопированный по указателю массив. Заодно можно ожидать проблем с памятью.

P.S. Если сказал чушь - буду признателен за указание, где именно.
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813247
Opus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вообще, мысль интересная, но вот в чем тогда вопрос: при создании объекта для него создается своей собственный массив koefs , в который затем копируется содержимое массива, переданного конструктору. Так что изменение содержимого массива у одного из объектов не должно сказываться на других, ведь массивы по сути разные.
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813255
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
int main(void)
{
	double k1[] = { 1 ,  2 ,  3 };
	Polynom p1( 2 , k1);
        Polynom p2 = p1;
Что-то подсказывает мне, что после этого массивы коэффициентов будут одинаковыми. Хотя могу и ошибиться - все ж таки уже много лет не занимался плюсами.
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813260
Opus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В данном случае да, согласен. Более того, p1 и p2 будут вообще на один объект ссылаться (или нет?). Только у меня подобных вещей нет, присваивается результат выполнения операции над двумя объектами (во всяком случае, так задумано :)).
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813289
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OpusВ данном случае да, согласен. Более того, p1 и p2 будут вообще на один объект ссылаться (или нет?). Только у меня подобных вещей нет, присваивается результат выполнения операции над двумя объектами (во всяком случае, так задумано :)).
Вам так кажется.
Вы пытаетесь передавать Polynom по значению , что приводит к копированию... Оператор копирования не описан -> побайтное копирование -> ссылка на один и тот же массив koefs в двух или более объектах класса...
...
Далее следует как минимум два вызова delete[] для каждого koefs...
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813301
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OpusБолее того, p1 и p2 будут вообще на один объект ссылаться (или нет?)
Для того, чтобы куда-нибудь ссылаться, им пришлось бы быть указателями. Такое впечатление, что Вы не очень внимательно читали про "чем объекты в C++ отличаются от объектов Delphi или Java".

Хм. В любом случае, с моей точки зрения сказано более чем достаточно для исправления ситуации.
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813305
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarerХм. В любом случае, с моей точки зрения сказано более чем достаточно для исправления ситуации.
Примерно так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Polynom::Polynom(Polynom& p)
{
	this->power = p.power;
	this->koefs = new double[power +  1 ];
	for (int i =  0 ; i <= power; i++)
	{
		this->koefs[i] = p.koefs[i];
	};
}
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813306
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousПримерно так:
:) По дельфовой привычке подумал - зачем копировать код, когда можно просто вызвать первый конструктор с параметрами p.power и p.koefs :)
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813343
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer andrey_anonymousПримерно так:
:) По дельфовой привычке подумал - зачем копировать код, когда можно просто вызвать первый конструктор с параметрами p.power и p.koefs :)
Вообще да. Но меня немного смущают авторские методы - классы передаются по значению, массивы нумеруются с единицы... И вообще код какой-то не си-плюс-плюсный :)
Кстати, оператор присваивания тоже нужен.
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813420
Фотография PPA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Рассмотри вариант замены указателя на std::vector
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813706
Opus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymousНо меня немного смущают авторские методы - классы передаются по значению, массивы нумеруются с единицы... И вообще код какой-то не си-плюс-плюсный :)
Массив у меня с 0 вообще-то. А что код не плюсный - просто всю жизнь на Java, а тут вдруг приспичило на плюсах накатать кой-чего.. Непривычно :)
Насчет передачи классов по значению - во всех попадавшихся мне примерах было так. Значит, стоит переписать методы, чтобы они возвращали не Polynom , а Polynom& ?
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813729
Фотография PPA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И принимать на вход желательно (const Polynom&) это исключит копирование
объекта.
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813736
Opus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PPAИ принимать на вход желательно (const Polynom&) это исключит копирование
объекта.
Должно получиться что-то вроде:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
Polynom& Polynom::operator+ (const Polynom& poly)
{
    ...
    Polynom& p = new Polynom(...);
    ...
    return p;
}
Так? А в коде это как будет вызываться? Что-то типа так что ли:
Код: plaintext
1.
2.
3.
4.
Polynom *p1, *p2, *p3;
p1 = new Polynom(...);
p2 = new Polynom(...);
p3 = (*p1) + p2;
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813919
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хм. Может быть, я уже совсем забыл C++, но имхо проблема в том, что Вы вовсю возвращаете локальные объекты. Я не помню, как ведет себя компилятор в этом случае, но в принципе у него два выхода:

Обычно он выдает предупреждения, если их не подавить.

либо таки вернуть указатель на мусор в стеке, либо вернуть копию локального объекта;

Первое.

подозреваю, он идет вторым путем.

Нет, первое.


operator= и конструктор копирования также нужны, иначе разные объекты будут разделять одно и то же состояние (точнее его часть, массив double),
а поддержки этого нет в коде. Хотя чтобы добавить поддержку также нужны конструктор копирования и оператор присваивания.
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813931
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot Opus]
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
Polynom& Polynom::operator+ (const Polynom& poly)
{
    ...
    Polynom& p = new Polynom(...);
    ...
    return p;
}
Так? А в коде это как будет вызываться? Что-то типа так что ли:
[.quot]

Такое надо возвращать по значению

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
Polynom Polynom::operator+ (const Polynom& right)
{
    Polynom res(...);
    res.plus( *this , right)
    ...
    return res;
}

Нельзя выделять результат в хипе , его некому будет удалять.
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813951
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
#include <iostream>

class Polynom
{
private:
	int power;
	double *koefs;
	void copy(const Polynom& right);

public:
	Polynom(int power, const double* koefs);
	Polynom(const Polynom& right);
             Polynom& operator=(const Polynom& right);

	virtual ~Polynom();
	
	double getValue(double argument);
	
	Polynom add(const Polynom& right);
	Polynom sub(const Polynom& right);
	Polynom multiply(const Polynom& right);
	
	Polynom operator+ (const Polynom& right);
	Polynom operator- (const Polynom& right);
	Polynom operator- ();
	Polynom operator* (const Polynom& right);
	friend ostream& operator<< (ostream& os, const Polynom& right);

};

ostream& operator<< (ostream& os, const Polynom& right);

...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813991
Opus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за подсказки, буду пробовать, как до дома дойду
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33813997
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
#include "Polynom.h"
#include <math.h>

Polynom::Polynom(int power, const double* koefs)
: power( 0 ), koefs(NULL)
{
	this->power = power;
	this->koefs = new double[power +  1 ];
	for (int i =  0 ; i <= power; ++i)
	{
	   this->koefs[i] = koefs[i];
	};
}

void Polynom::copy(const Polynom& right)
{
             if( koefs && power != right.power) 
               { delete[] koefs; koefs = NULL; }
	power = right.power;
             if( !koefs ) 
	  koefs = new double[power +  1 ];

             // вообще -то можно и memcpy использовать,
             // которая часто вообще в одну ассемблерную комманду компилируется.
	for (int i =  0 ; i <= power; ++i)
	{
	   koefs[i] = right.koefs[i];
	};
}

Polynom::Polynom(const Polynom& right)
{
   if( this != &right)
     copy(right);
}

Polynom& Polynom::operator=(const Polynom& right)
{
   if( this != &right)
     copy(right);
}

Polynom::~Polynom()
{
  if( koefs )
  { delete[] koefs; koefs = NULL; }
}

double Polynom::getValue(double argument)  const
{
	double result =  0 ;
	for(int i =  0 ; i <= power; ++i)
	{
		result += koefs[i -  1 ] * pow(i, argument);
	};
	return result;
}

Polynom Polynom::add(cons Polynom& poly)  const
{
	Polynom* bigger = (power > poly.power) ? this : &poly;
	Polynom* smaller = (power < poly.power) ? this : &poly;
	Polynom newPoly(bigger->power, bigger->koefs);
	
	for (int i =  0 ; i <= smaller->power; ++i)
	{
		newPoly.koefs[i] += smaller->koefs[i];
	};
	
	return newPoly;
}

Polynom Polynom::sub(cons Polynom& poly)  const
{
	Polynom p = - poly;
	return add(p);
}

Polynom Polynom::multiply(cons Polynom& poly)  const
{
	int p = power + poly.power;
	double* kfs = new double[p +  1 ];
	for (int c =  0 ; c <= p; ++c)
	{
		kfs[c] =  0 ;
	};
	
	for (int i =  0 ; i <= power; ++i)
	{
		for (int j =  0 ; j <= poly.power; ++j)
		{
			kfs[i + j] += koefs[i] * poly.koefs[j];
		};
	};
	
	Polynom newPoly(p, kfs);
	delete[] kfs; // эта переменная не должна динамически выделяться.
            // можно использовать newPoly.koefs, если объявить его раньше.
	return newPoly;
}

Polynom Polynom::operator+(cons Polynom& poly)  const
{
	return add(poly);
}

Polynom Polynom::operator-(cons Polynom& poly)  const
{
	return sub(poly);
}

Polynom Polynom::operator-() const
{
	Polynom p(power, koefs);
	for (int i =  0 ; i <= p.power; ++i)
	{
		p.koefs[i] = (- 1 ) * p.koefs[i];
	};
	return p;
}

Polynom Polynom::operator*(Polynom poly)
{
	return multiply(poly);
}

ostream& operator<<(ostream& os, Polynom poly)
{
	for (int i = poly.power; i >= 0 ; --i)
	{
		os << poly.koefs[i] << " ";
	};
	return os;
}

...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33814001
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv
Код: plaintext
1.
2.
3.
4.
5.
6.
#include <iostream>

class Polynom
{
};



Там почти все методы-операции должны быть const, я забыл поставить.
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33815521
Opus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо :) Правда, уже сам до почти похожего докопался, вроде работает :)
Кстати, пардон за баналность, а что такое const в сигнатуре метода?
...
Рейтинг: 0 / 0
Меняются поля класса, хотя и не должны
    #33815608
Фотография PPA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OpusСпасибо :) Правда, уже сам до почти похожего докопался, вроде работает :)
Кстати, пардон за баналность, а что такое const в сигнатуре метода?

Это говорит о том, что метод не модифицирует состояние объекта
(т.е. явно или косвенно не меняет своих мемберов)
...
Рейтинг: 0 / 0
25 сообщений из 25, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Меняются поля класса, хотя и не должны
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]