| Другое > Hard'n'Soft |
| Програмирование на C++ |
| << < (9/25) > >> |
| 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, он часто глупости говорит. Или хотя бы обдумывай его слова, а не верь на слово. А ещё плохо знаком с сабжем, раз осмеивает возможность присвоения объекту самому себе. |
| Навигация |
| Главная страница сообщений |
| Следующая страница |
| Предыдущая страница |