конструкторы

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Почему вызовы delete располагаются в методе show? Они должны быть в деструкторе! При текущем положении дел метод show вызвать больше одного раза нельзя, а это неправильно.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Евгений Александрович
Сообщения: 82
Зарегистрирован: 19 дек 2009, 16:48

Проблема: при выводе данных( а в частности проблема с выводом полей "value") то обрезаются данные, то заполняются лишними(в зависимости от ввода vc);
Т.е. нормально работает, если только первый размер(за размерность отвечает vc) = вотрому размеру.

Код: Выделить всё

class bank
{   
private:
	char *bank_name;
	char **name;
	int **value;
	int **salary;
public:
	bank(){}
	void add(int );
	void show(int );
};
int vc;
void bank::add(int n)
{
    bank_name=new char[33];
    cout<<"input bank_name\n"<<endl;
	cin>>bank_name;

	char str[55];
	name=new char *[n];
	value=new int *[n];
	salary=new int *[n];
for(int i=0;i<n;i++)
{
	system("cls");
	cout<<i<<":iput name:\n"<<endl;
	cin>>str;
	name[i]=new char[strlen(str)+1];
	strcpy(name[i],str);

	cout<<"input amount of values:";
cin>>vc;
value[i]=new int[vc];
salary[i]=new int[vc];
for(int j=0;j<vc;j++)
{
	cout<<"values:"<<j<<endl;
cin>>value[i][j];
cout<<"salary:"<<endl;
cin>>salary[i][j];
}
}
system("cls");
}
void bank::show(int n)
{
	cout<<bank_name<<endl;
	for(int i=0;i<n;i++)
	{
	cout<<name[i]<<"\n";
	for(int j=0;j<vc;j++)
	{
   cout<<value[i][j]<<" "<<salary[i][j]<<endl;
	}
	}
}

void main()
{
	char **name='\0',*bank_name='\0';int *value=0;
	int n;
	bank object;
	cout<<" size (n):"<<endl;
	cin>>n;
	bank obj;
	obj.add(n);
	obj.show(n);
	system("PAUSE");
	delete []name;
	delete []bank_name;
	delete []value;
}
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Слушай, я просто поражаюсь, как ты умудряешься сделать всё максимально неправильно.

1. Что это первая строка в main? Зачем нужны эти переменные?
2. Зачем делать этим переменных в конце delete, если ты им ни разу не делал new?
3. Зачем n хранить снаружи и передавать как в метод add, так и в метод show, что вообще является ужасным. Объект сам должен знать сколько в нём элементов: n сама просится быть внесённой в класс, в качестве поля, неужели это не очвидно?
4. Куда дела деструктор класс bank. Я уже писал о деструкторе 3 раза. В нём должна удаляться память. Где он?
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Евгений Александрович
Сообщения: 82
Зарегистрирован: 19 дек 2009, 16:48

Сделал по вашим советам. Появилась проблема: ввожу размерность n - все норм, а вот уже после ввода имени банка - ошибка(debug library). Что ж опять то не так?

Код: Выделить всё

class bank
{   
private:
	char *bank_name;
	char **name;
	int **value;
	int **salary;
public:
	int n;
	bank(){}
	~bank();
	void add( );
	void show( );
};
int vc;
void bank::add()
{
    bank_name=new char[33];
    cout<<"input bank_name\n"<<endl;
	cin>>bank_name;

	char str[55];
	name=new char *[n];
	value=new int *[n];
	salary=new int *[n];
for(int i=0;i<n;i++)
{
	system("cls");
	cout<<i<<":iput name:\n"<<endl;
	cin>>str;
	name[i]=new char[strlen(str)+1];
	strcpy(name[i],str);

	cout<<"input amount of values:";
cin>>vc;
value[i]=new int[vc];
salary[i]=new int[vc];
for(int j=0;j<vc;j++)
{
	cout<<"values:"<<j<<endl;
cin>>value[i][j];
cout<<"salary:"<<endl;
cin>>salary[i][j];
}
}
system("cls");
}
void bank::show()
{
	cout<<bank_name<<endl;
	for(int i=0;i<n;i++)
	{
	cout<<name[i]<<"\n";
	for(int j=0;j<vc;j++)
	{
   cout<<value[i][j]<<" "<<salary[i][j]<<endl;
	}
	}
}
bank::~bank()
{
	delete []name;
	delete []bank_name;
	delete []value;
}
void main()
{
	int n;
	bank object;
	cout<<" size (n):"<<endl;
	cin>>n;
	bank obj;
	obj.add();
	obj.show();
	system("PAUSE");
}
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Ты n сделал поле класса, но нигде его не проставляешь. Этот код не должен работать. Неужели работает? :) Ты хоть раз запускал его?

Раньше у тебя был дефолтный конструктор реализован. Где он сейчас делся?
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Евгений Александрович
Сообщения: 82
Зарегистрирован: 19 дек 2009, 16:48

Заработало, но возникла проблема: выводит еще какое-то лишнее число если размерность value одного человека не совпадает с размерностью другого.

Код: Выделить всё

class bank
{   
private:
	char *bank_name;
	char **name;
	int **value;
	int **salary;
public:
	int n;
	bank();
	~bank();
	void add( );
	void show( );
	void setsize();
};
int vc;
bank::bank()
{
	 n=0;
	 int **value=0,**salary=0;
	 char **name='\0',*bank_name='\0';
}
void bank::setsize()
{
	cout<<" size (n):"<<endl;
	cin>>n;
}
void bank::add()
{
    bank_name=new char[33];
    cout<<"input bank_name\n"<<endl;
	cin>>bank_name;

	char str[55];
	name=new char *[n];
	value=new int *[n];
	salary=new int *[n];
for(int i=0;i<n;i++)
{
	system("cls");
	cout<<i<<":iput name:\n"<<endl;
	cin>>str;
	name[i]=new char[strlen(str)+1];
	strcpy(name[i],str);

	cout<<"input amount of values:";
cin>>vc;
value[i]=new int[vc];
salary[i]=new int[vc];
for(int j=0;j<vc;j++)
{
	cout<<"values:"<<j<<endl;
cin>>value[i][j];
cout<<"salary:"<<endl;
cin>>salary[i][j];
}
}
system("cls");
}
void bank::show()
{
	cout<<bank_name<<endl;
	for(int i=0;i<n;i++)
	{
	cout<<name[i]<<"\n";
	for(int j=0;j<vc;j++)
	{
   cout<<value[i][j]<<" "<<salary[i][j]<<endl;
	}
	}
}
bank::~bank()
{
	delete []name;
	delete []bank_name;
	delete []value;
	delete []salary;
}
void main()
{
	bank obj;
	obj.setsize();
	obj.add();
	obj.show();
	system("PAUSE");
}
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Уже лучше. Осталась одна проблема - именно та, которую ты описал. А источник её - глобальная переменная vc. Из-за того, что она глобальная, переменная переписывается при каждом новом вызове cin<<vc и под конец выполнения add содержит самое последнее значение amount. С другой стороны, в методе show использует снова эта же самая переменная, поэтому для всех клиентов будут выводится количество value такое, как было у последнего клиента, а это ошибка, ведь количество value у каждого клиента своё и поэтому ты будешь залезать в "чужую" память, если количество предыдущих value меньше, либо просто недовыводить все value, если количество предыдущих value больше.

Исправляется ошибка просто. Глобальную переменную vс нужно уничтожить. Её должно заменить поле класса например с тем же именем vc типа - массив int'ов, которое будет хранить количество values для каждого клиента. В методе add нужно выделять под этот массив n элементов, затем i-й элемент считывать из потока. Также нужно поменять все циклы, которые бегут до vc, чтобы они бежали до vc. Ну и в конце не забыть удалить выделенную под vc память в деструкторе класса.

Вот и вся премудрость :)
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Евгений Александрович
Сообщения: 82
Зарегистрирован: 19 дек 2009, 16:48

Огромное спасибо Вам, идеально заработало. Не так то просто было.
Ответить