Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Меняются поля класса, хотя и не должны / 25 сообщений из 25, страница 1 из 1
24.06.2006, 15:12
    #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
24.06.2006, 22:18
    #33813150
Lelikk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
На гуще не гадаем ))

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

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

P.S. Если сказал чушь - буду признателен за указание, где именно.
...
Рейтинг: 0 / 0
25.06.2006, 10:47
    #33813247
Opus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
Вообще, мысль интересная, но вот в чем тогда вопрос: при создании объекта для него создается своей собственный массив koefs , в который затем копируется содержимое массива, переданного конструктору. Так что изменение содержимого массива у одного из объектов не должно сказываться на других, ведь массивы по сути разные.
...
Рейтинг: 0 / 0
25.06.2006, 11:09
    #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
25.06.2006, 11:33
    #33813260
Opus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
В данном случае да, согласен. Более того, p1 и p2 будут вообще на один объект ссылаться (или нет?). Только у меня подобных вещей нет, присваивается результат выполнения операции над двумя объектами (во всяком случае, так задумано :)).
...
Рейтинг: 0 / 0
25.06.2006, 13:14
    #33813289
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
OpusВ данном случае да, согласен. Более того, p1 и p2 будут вообще на один объект ссылаться (или нет?). Только у меня подобных вещей нет, присваивается результат выполнения операции над двумя объектами (во всяком случае, так задумано :)).
Вам так кажется.
Вы пытаетесь передавать Polynom по значению , что приводит к копированию... Оператор копирования не описан -> побайтное копирование -> ссылка на один и тот же массив koefs в двух или более объектах класса...
...
Далее следует как минимум два вызова delete[] для каждого koefs...
...
Рейтинг: 0 / 0
25.06.2006, 13:35
    #33813301
softwarer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
OpusБолее того, p1 и p2 будут вообще на один объект ссылаться (или нет?)
Для того, чтобы куда-нибудь ссылаться, им пришлось бы быть указателями. Такое впечатление, что Вы не очень внимательно читали про "чем объекты в C++ отличаются от объектов Delphi или Java".

Хм. В любом случае, с моей точки зрения сказано более чем достаточно для исправления ситуации.
...
Рейтинг: 0 / 0
25.06.2006, 13:46
    #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
25.06.2006, 13:50
    #33813306
softwarer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
andrey_anonymousПримерно так:
:) По дельфовой привычке подумал - зачем копировать код, когда можно просто вызвать первый конструктор с параметрами p.power и p.koefs :)
...
Рейтинг: 0 / 0
25.06.2006, 15:26
    #33813343
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
softwarer andrey_anonymousПримерно так:
:) По дельфовой привычке подумал - зачем копировать код, когда можно просто вызвать первый конструктор с параметрами p.power и p.koefs :)
Вообще да. Но меня немного смущают авторские методы - классы передаются по значению, массивы нумеруются с единицы... И вообще код какой-то не си-плюс-плюсный :)
Кстати, оператор присваивания тоже нужен.
...
Рейтинг: 0 / 0
25.06.2006, 18:14
    #33813420
PPA
PPA
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
Рассмотри вариант замены указателя на std::vector
...
Рейтинг: 0 / 0
26.06.2006, 09:10
    #33813706
Opus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
andrey_anonymousНо меня немного смущают авторские методы - классы передаются по значению, массивы нумеруются с единицы... И вообще код какой-то не си-плюс-плюсный :)
Массив у меня с 0 вообще-то. А что код не плюсный - просто всю жизнь на Java, а тут вдруг приспичило на плюсах накатать кой-чего.. Непривычно :)
Насчет передачи классов по значению - во всех попадавшихся мне примерах было так. Значит, стоит переписать методы, чтобы они возвращали не Polynom , а Polynom& ?
...
Рейтинг: 0 / 0
26.06.2006, 09:24
    #33813729
PPA
PPA
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
И принимать на вход желательно (const Polynom&) это исключит копирование
объекта.
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
26.06.2006, 09:30
    #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
26.06.2006, 10:38
    #33813919
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
Хм. Может быть, я уже совсем забыл C++, но имхо проблема в том, что Вы вовсю возвращаете локальные объекты. Я не помню, как ведет себя компилятор в этом случае, но в принципе у него два выхода:

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

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

Первое.

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

Нет, первое.


operator= и конструктор копирования также нужны, иначе разные объекты будут разделять одно и то же состояние (точнее его часть, массив double),
а поддержки этого нет в коде. Хотя чтобы добавить поддержку также нужны конструктор копирования и оператор присваивания.
...
Рейтинг: 0 / 0
26.06.2006, 10:42
    #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
26.06.2006, 10:46
    #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
26.06.2006, 10:59
    #33813991
Opus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
Спасибо за подсказки, буду пробовать, как до дома дойду
...
Рейтинг: 0 / 0
26.06.2006, 11:01
    #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
26.06.2006, 11:01
    #33814001
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Меняются поля класса, хотя и не должны
MasterZiv
Код: plaintext
1.
2.
3.
4.
5.
6.
#include <iostream>

class Polynom
{
};



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

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


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