Другое > Hard'n'Soft
Програмирование на C++
gepar:
Но как сделать проверку что это не самоприсваивание, больше вникать никуда не надо, мне нужно лишь проверить что объект класса не присваивается самому себе, всё остальное работает.
Остальное кстати вот:
--- Код: ---# include <iostream>
# include <iomanip>
using namespace std;
class Array
{
friend ostream &operator<<(ostream &output, Array &test);
friend ostream &operator>>(ostream &output, Array &test);
public:
//конструктор по умолчанию
Array(int a, int b)
{
row=(a>0) ? a:1;
column=(b>0)? b:1;
ptr= new int [row*column+1];
for (int i=1;i<row*column+1;i++)
ptr[i]=0;
}
//конструктор копии в который я не могу добавить проверку на самоприсваивание
Array (const Array &abc)
{
if (row!=abc.row || column!=abc.column)
{
delete []ptr;
row=abc.row;
column=abc.column;
ptr=new int[row*column+1];
}
for (int i=0;i<row*column+1;i++)
ptr[i]=abc.ptr[i];
}
//возможность обращения к нужному элементу массива
int &operator()(int a, int b)
{
if ((a>0) && (a<=row) &&(b>0) && (b<=column))
if (a==1)
return ptr[a+b];
else
return ptr[(a-1)*column+b];
else
exit(100500);
}
//возможность обращения к нужному элементу массива для const объекта класса
int &operator()(int a, int b) const
{
if ((a>0) && (a<=row) &&(b>0) && (b<=column))
if (a==1)
return ptr[a+b];
else
return ptr[(a-1)*column+b];
else
exit(100500);
}
//проверка на равенство
bool operator==(Array test)
{
if ((row!=test.row) || (column!=test.column))
return false;
for (int j=0;j<row*column+1;j++)
if (ptr[j]!=test.ptr[j])
return false;
return true;
}
//проверка на неравенство
bool operator !=(Array test)
{
return !(*this==test);
}
private:
int row; //колличество строк
int column; //колличество столбцов
int *ptr; //указатель на массив с элементами int
};
ostream &operator<<(ostream &output, Array &test)
{
output<<endl;
for (int i=1;i<((test.row*test.column)+1);i++)
{
output<<setw(3)<<test.ptr[i]<<" ";
if ((i)%test.column==0)
output<<endl;
}
return output;
}
ostream &operator>>(ostream &output, Array &test)
{
output<<endl;
for (int i=1;i<((test.row*test.column)+1);i++)
output<<setw(3)<<test.ptr[i]<<" ";
output<<endl;
return output;
}
int main()
{
Array a(2,3);
a(1,1)=3;
a(2,2)=5;
Array b(5,5);
b(1,4)=10;
b(3,3)=20;
cout<<"a=b ? : "<<boolalpha<<(a!=b);
cout<<"\nA:"<<a<<"B:"<<b;
return 0;
}
--- Конец кода ---
Mr2:
gepar,
Ты понял почему писать if (*this!=abc); нельзя?
gepar:
Mr2,нет, я только понял что нельзя :)
Mr2:
--- Цитата: gepar от 17 Марта 2011, 00:48:52 ---Mr2,нет, я только понял что нельзя :)
--- Конец цитаты ---
if можно писать двумя способами:
------------1-------------------
if(a!=b)
cout << а <<endl;
------------2-----------------------
if(a!=b){
cout << а <<endl;
cout << а <<endl;
}
-------------------------------------
--------фатал эррор :D-------------
if(a!=b);
cout << а <<endl;
-------------------------------------
gepar:
Mr2, а , ты об этом, я уже убирал ;, там не в ней дело, вот смотри:
--- Код: ---//свой класс-массив
//+ возможность получать min или max элемент массива
# include <iostream>
# include <iomanip>
# include <cstring>
using namespace std;
class Array
{
friend ostream &operator<<(ostream &output, Array &test);
friend ostream &operator>>(ostream &output, Array &test);
public:
//конструктор по умолчанию
Array(int a, int b)
{
row=(a>0) ? a:1;
column=(b>0)? b:1;
ptr= new int [row*column+1];
for (int i=1;i<row*column+1;i++)
ptr[i]=0;
}
//конструктор копии который не работает
Array (const Array &abc)
{
if (*this!=abc)
{
if (row!=abc.row || column!=abc.column)
{
delete []ptr;
row=abc.row;
column=abc.column;
ptr=new int[row*column+1];
}
for (int i=0;i<row*column+1;i++)
ptr[i]=abc.ptr[i];
}
else exit(1);
}
//возможность обращения к нужному элементу массива
int &operator()(int a, int b)
{
if ((a>0) && (a<=row) &&(b>0) && (b<=column))
if (a==1)
return ptr[a+b];
else
return ptr[(a-1)*column+b];
else
exit(100500);
}
//возможность обращения к нужному элементу массива для const объекта класса
int &operator()(int a, int b) const
{
if ((a>0) && (a<=row) &&(b>0) && (b<=column))
if (a==1)
return ptr[a+b];
else
return ptr[(a-1)*column+b];
else
exit(100500);
}
//возможность нахождения min/max элемента
int &operator()(string a)
{
if (a=="maximum")
{
int *max=&ptr[1];
for (int i=1;i<row*column+1;i++)
if (ptr[i]>*max)
max=&ptr[i];
return *max;
}
else if (a=="minimum")
{
int *min=&ptr[1];
for (int i=1;i<row*column+1;i++)
if(ptr[i]<*min)
min=&ptr[i];
return *min;
}
exit (1);
}
//проверка на равенство
bool operator==(Array test)
{
if ((row!=test.row) || (column!=test.column))
return false;
for (int j=0;j<row*column+1;j++)
if (ptr[j]!=test.ptr[j])
return false;
return true;
}
//проверка на неравенство
bool operator !=(Array test)
{
return !(*this==test);
}
private:
int row; //колличество строк
int column; //колличество столбцов
int *ptr; //указатель на массив с элементами int
};
ostream &operator<<(ostream &output, Array &test)
{
output<<endl;
for (int i=1;i<((test.row*test.column)+1);i++)
{
output<<setw(3)<<test.ptr[i]<<" ";
if ((i)%test.column==0)
output<<endl;
}
return output;
}
ostream &operator>>(ostream &output, Array &test)
{
output<<endl;
for (int i=1;i<((test.row*test.column)+1);i++)
output<<setw(3)<<test.ptr[i]<<" ";
output<<endl;
return output;
}
int main()
{
Array a(2,3);
a(1,1)=3;
a(2,2)=5;
Array b(5,5);
b(1,4)=10;
b(3,3)=20;
cout<<"a=b ? : "<<boolalpha<<(a==b);
cout<<"\nA:"<<a<<"B:"<<b;
cout<<b("maximum");
return 0;
}
--- Конец кода ---
Добавлено позже:
+ мне по прежнему интересно почему будет крешится программа с этой неправильной проверкой в конструкторе если в main он (констркутор копии) использоваться НЕбудет, но будет использоваться сравнение (== или !=). Вот сам попробуй убрать строку в main где используется сравнение и программа скомпилируется и будет работать нормально, но где же связь? Операции сравнения у меня никак не используют конструктор копии же.
Mr2:
Я не понимаю твой код. :(
Ты опиши проблему я мож чего найду.
--- Цитата ---//конструктор копии в который я не могу добавить проверку на самоприсваивание
--- Конец цитаты ---
Непонятно в каком случае происходит самокопирование?
Я читал что может быть неверное копирование связаное с адресами, а про само копирование не в курсе.
Пойду вникать в тонкости конструктора копирования. ;)
HoRRoR:
row*column+1 - зачем +1? Количество элементов матрицы NxM и равно NxM.
Непонятно, как ты используешь exit() без cstdlib.
--- Код: ---if (*this!=abc)
--- Конец кода ---
Ай-яй-яй, не делают так. К тому же, у тебя оператор сравнения перегружен. Сравнивают адреса:
--- Код: ---if (this!=&abc)
--- Конец кода ---
Чуть ниже:
--- Код: ---delete []ptr;
--- Конец кода ---
А что ты, собственно, удаляешь? Ты разве выделял память под этот ptr? Нафиг эту строку.
И вообще, замени
--- Код: ---bool operator==(Array test)
bool operator!=(Array test)
--- Конец кода ---
на
--- Код: ---bool operator==(const Array& test)
bool operator!=(const Array& test)
--- Конец кода ---
Негоже каждый раз для сравнения создавать копию массива.
--- Код: --- if (a=="maximum")
...
else if (a=="minimum")
--- Конец кода ---
Ну кто так делает? Это верх нерациональности. Заведи консанты или enum - {A_MAX, A_MIN}, принимай int или переменную типа этого enum'а, а там уже сравнивай или через switch выполняй необходимые действия.
Остальной код не смотрел, на этом всё заработало, дальше уж сам ищи ляпы.
gepar:
--- Цитата: HoRRoR ---row*column+1 - зачем +1? Количество элементов матрицы NxM и равно NxM.
--- Конец цитаты ---
да это я чтобы пропустить элемент 0.
--- Цитата: HoRRoR ---Непонятно, как ты используешь exit() без cstdlib.
--- Конец цитаты ---
Компилируется так - я и не использую :)
--- Цитата: HoRRoR ---Ай-яй-яй, не делают так. К тому же, у тебя оператор сравнения перегружен. Сравнивают адреса:
--- Конец цитаты ---
Понял, буду знать.
--- Цитата: HoRRoR ---А что ты, собственно, удаляешь? Ты разве выделял память под этот ptr? Нафиг эту строку.
--- Конец цитаты ---
Ну а если у меня сначала было Array a(5,5) .... а потом уже a=b, следовательно место под a изначально было же выделено.
По поводу того чтобы не копировались мои массивы для сравнения исправлю, спасибо за подсказку.
--- Цитата: HoRRoR ---Ну кто так делает? Это верх нерациональности. Заведи консанты или enum - {A_MAX, A_MIN}, принимай int или переменную типа этого enum'а, а там уже сравнивай или через switch выполняй необходимые действия.
--- Конец цитаты ---
Не читал я ещё о enum, посмотрю что он из себя представляет. Через switch идея была сделать.
Ну и спасибо за конструктивную критику :)
Mr2:
gepar,
А что ты хотел проверить в if (*this!=abc)?
Совпадают ли адрес нового(this) объекта с существующим(abc)?
Вот нормальный массив:
--- Код: ---//Безопастный целочисленный массив.
//Автор Г. Шилдт.
#include <iostream>
#include <new>
#include <cstdlib>
using namespace std;
class array{
int *p;
int size;
public:
array(int cz){
try{
p = new int[cz];
}
catch(bad_alloc xa){
cout << "error constr\n";
exit(EXIT_FAILURE);
}
size = cz;
}
~array(){
delete[] p;
}
array(const array &a);
void put(int i, int j){
if(i>=0 && i<size) p[i] =j;
}
int get(int i){
return p[i];
}
};
array::array(const array &a){
int i;
try{
p = new int[a.size];
}
catch(bad_alloc xa){
cout << "Copy constr error\n";
exit(EXIT_FAILURE);
}
for(i=0; i<a.size;i++)
p[i] = a.p[i];
}
int main(){
array num(10);
int i;
for(i = 0; i<10; i++)
num.put(i,i);
for(i=9; i>=0; i--)
cout << num.get(i);
cout << "\n";
array x(num); //включаем копирующий конструктор.
for(i=0; i<10; i++)
cout<< x.get(i);
cout <<"\n";
system("pause");
return 0;
}
--- Конец кода ---
gepar:
Mr2,да, я хотел проверить не будет ли самокопирование, которое может привести к ошибкам в некоторых случаях, ну да HoRRoR уже написал что нужно было адрес сравнивать, сейчас попробую поисправлять все те ошибки что я допустил.
Mr2:
--- Цитата: gepar ---Mr2,да, я хотел проверить не будет ли самокопирование,
--- Конец цитаты ---
В каком случае будет самокопирование? :?
array a;
a=a;
ты об этом?
gepar:
Mr2,
array a;
a=a ну или a(a).
Mr2:
--- Цитата: gepar от 17 Марта 2011, 16:08:17 ---Mr2,
array a;
a=a ну или a(a).
--- Конец цитаты ---
Я прочитал твою мысль на расстоянии. :lol:
Только непонятно кто будет делать такое присвоение, и какой смысл в нём. :?
gepar:
Mr2, смысл в том что это приведёт к неработоспособности программы, эдакая дыра, так зачем же её держать открытой?
Mr2:
--- Цитата: gepar от 17 Марта 2011, 16:17:11 ---Mr2, смысл в том что это приведёт к неработоспособности программы, эдакая дыра, так зачем же её держать открытой?
--- Конец цитаты ---
Как я понял спровацировать её(ошибку) может только сам программист, пользователь(программы) по идее не может заставить объект самокопироваться. Ну а присвоить объект самому себе придёт в голову только особо извращённым индивидам. :lol:
То же самое что
int i = 3;
i=i;
:lol:
gepar:
Mr2,ну а если была ссылка на a, а потом уже и не помнишь что это ссылка на a и пытаешься этой ссылке присвоить a, а? :)
Mr2:
--- Цитата: gepar от 17 Марта 2011, 16:27:47 ---Mr2,ну а если была ссылка на a, а потом уже и не помнишь что это ссылка на a и пытаешься этой ссылке присвоить a, а? :)
--- Конец цитаты ---
Да тебе определённо нужно сделать проверку. :)
Вообще с выделением памяти, указателями нужно быть аккуратнее и не пихать их везде где можно без них обойтись.
Я их вообще редко использую.Ну просто необходимости особой не возникает.Я только сегодня вник в копирующий конструктор, до этого просто знал что он есть и когда его нужно использовать. ^_^
gepar:
--- Цитата: Mr2 ---Вообще с выделением памяти, указателями нужно быть аккуратнее и не пихать их везде где можно без них обойтись.
--- Конец цитаты ---
А это почему же?
Mr2:
--- Цитата: gepar от 17 Марта 2011, 16:42:33 ---А это почему же?
--- Конец цитаты ---
Ну если твоя программа состоит из пары строк то ничего страшного.
А вот если из пары сотен, то тут уже будет трудно найдти какой указатель шалит(заставляет аварийно завершиться программу)
или почему кончилась память. Тем более если ты " не помнишь что это ссылка на a и пытаешься этой ссылке присвоить a". :)
HoRRoR:
--- Цитата ---да это я чтобы пропустить элемент 0.
--- Конец цитаты ---
Неоправданная избыточность информации - плохой тон. Уменьшай индекс на 1. А если ты перепишешь класс под шаблоны и в каком-либо случае у тебя элементами будут служить объекты по 100МБ?
--- Цитата ---Ну а если у меня сначала было Array a(5,5) .... а потом уже a=b, следовательно место под a изначально было же выделено.
По поводу того чтобы не копировались мои массивы для сравнения исправлю, спасибо за подсказку.
--- Конец цитаты ---
Во-первых, при создании присваивай переменной NULL, а при удалении делай так:
--- Код: ---if(ptr)
{
delete []ptr;
ptr = NULL;
}
--- Конец кода ---
В прочем, если ты тут же выделяешь память, то присваивать NULL нет необходимости.
--- Цитата ---Компилируется так - я и не использую
--- Конец цитаты ---
Что ты используешь? У меня в CodeBlocks не компилировалось, посмотрел мануалы - exit() объявлена в cstdio. Привыкнешь ещё, а потом будешь удивляться почему не компилируется в других средах...
--- Цитата ---Не читал я ещё о enum, посмотрю что он из себя представляет. Через switch идея была сделать.
--- Конец цитаты ---
Это очень просто. enum [имя] {<элемент1>[=значение][, элемент2[=значение2], элемент3[=значение3], ...]} [переменные];
Т.е. enum X {a, b, c}; объявит перечисление X с элементами a, b, c, имеющими значения 0, 1, 2. Далее в коде их можно использовать как константы. Можно сделать так: enum {a = 10, b = 20, c}; - объявление безымянного перечисления, a=10, b=20, c=21.
P.S. Поменьше слушай Mr2, он часто глупости говорит. Или хотя бы обдумывай его слова, а не верь на слово.
А ещё плохо знаком с сабжем, раз осмеивает возможность присвоения объекту самому себе.
Навигация
Перейти к полной версии