| Другое > Hard'n'Soft |
| Програмирование на C++ |
| << < (11/25) > >> |
| HoRRoR:
--- Код: ---Понятно. То есть эффективность в основном в условной компиляции. --- Конец кода --- Да как бы сказать... это единственный способ условной компиляции. Ну если не считать шаблоны за условную компиляцию. Так что о эффективности можно не говорить. --- Код: ---Ато что-то я в преподше моей по с++ разочаровался --- Конец кода --- Да с преподавателями вообще беда. Они в основном теоретики и зачитывают наизусть заученные тексты, многое не понимая и постоянно делая ляпы. Наша преподавательница работала программистом C#, но читала курс C++. Постоянно делала ляпы, не знала что такое GNU GCC, т.е. ни с чем, кроме студии, не работала. Сначала с ней спорил, думая, что она действительно так считает. А оказывается она просто толком ничего не знает :D --- Код: ---а выделение памяти через maloc, а удаление через delete (хотя это я уже придираюсь) ... --- Конец кода --- Да нет, это грубая ошибка. Всё зависит от реализации, конечно, но обычно используются разные методы для выделения памяти, следовательно - разные механизмы её высвобождения. Т.е. в реализациях с разными механизмами гарантирована в лучшем случае утечка памяти. Вообще советую new использовать для объектов (тем более, что он вызывает конструктор) и массивов переменных, а malloc/calloc - для обычных данных (графика, например, или буфер - в общем, не переменные). |
| gepar:
А когда я делаю конструктор для инициализации элемента класса элементом другого класса (композиция) то получается я обязан делать и конструктор по умолчанию (хотя бы пустой ничего не делающий с {}) иначе в main я не смогу создать новый объект моего класса не передавая ничего, ну не смогу написать: myclass a; почему так? Ведь не делай я конструктор на случай если я потом захочу присвоить объекту myclass a значение другого класса то я спокойно могу сделать в main myclass a; и никаких пустых конструкторов по умолчанию при этом делать не надо, почему так? Опять стандарт? Собственно пример если я непонятно выразился (пример из конспекта преподши, просто решил переделать от скуки чтобы можно было инициализировать объект одного класса значениями другого, сам пример изначально наоборот демонстрировал что этого делать нельзя :) ) : --- Код: ---#include<iostream> using namespace std; class myclass { public: int a,b; void set(int i, int j){a = i;b=j;} void show() { cout<< a <<' ' << b << "\n"; } }; class yourclass { int a,b; public: void set(int i, int j){a = i;b=j;} yourclass(){}; //Без этого не получиться создать в main yourclass o2 не передавая параметров в скобках yourclass(myclass &abc) {a=abc.a;b=abc.b;} void show() { cout<< a <<' '<< b << "\n"; } }; int main() { myclass o1; yourclass o2; o1.set(10,4); o2=o1; o1.show(); o2.show(); return 0; } --- Конец кода --- Все мелочи неточности и что нежелательно делать в этом примере, а было сделано давайте опустим :) Добавлено позже: Ну и заодно вопрос: можно ли объявить другом (friend) класса другой класс подскажите пожалуйста? Ну на случай что мне надо будет чтобы функции одного класса могли обращаться к приватным данным другого класса, я так догадываюсь это вполне реально ведь :) Я ведь пока знаю только как объявить функцию-друга класса только если эта функция будет за границей классов вообще. Добавлено позже: Вопрос N3: у преподши повсюду идёт проверка что память через malloc/new была выделена, это пережитки прошлого (когда оп было мало) чтоль или это хороший тон, хотя на последнее не очень то похоже. Это если бы я выделял память в большом объёме тогда ладно, но когда массив из 10 int объектов что не займёт много памяти то по-моему эта проверка лишняя ... или нет? |
| HoRRoR:
--- Цитата ---почему так? --- Конец цитаты --- Потому что если не описывать ни одного конструктора, то он будет создан автоматически - с пустым телом и без параметров, называется конструктор по умолчанию. А иначе ты сам описываешь конструкторы и можешь создавать объекты только с существующими конструкторами. Т.е. при наличии хоть одного конструктора не будет создаваться пустой конструктор по умолчанию. --- Цитата ---можно ли объявить другом (friend) класса другой класс подскажите пожалуйста? --- Конец цитаты --- А что мешало тебе проверить? Написать внутри класса friend class MyClass? Конечно можно. --- Цитата ---Вопрос N3 --- Конец цитаты --- Поясни, я о такой проверке не слышал, не приходилось использовать. А разницы в объёме нет - хоть один байт, хоть гигабайт - это выделенный блок памяти, так что не лишняя. Лишняя она если ты знаешь, где какой метод выделения памяти ты используешь и у тебя гарантированно не случается накладок. |
| gepar:
--- Цитата: HoRRoR ---Т.е. при наличии хоть одного конструктора не будет создаваться пустой конструктор по умолчанию. --- Конец цитаты --- Ага, теперь понятно. --- Цитата: HoRRoR ---А что мешало тебе проверить? Написать внутри класса friend class MyClass? Конечно можно. --- Конец цитаты --- Да ничего не мешало, не знал я как это сделать, пробовал писать просто friend MyClass, а компилятор сказал что так нельзя ну я и решил спросить. Теперь понятно, спасибо за ответ :) --- Цитата: HoRRoR ---оясни, я о такой проверке не слышал, не приходилось использовать. --- Конец цитаты --- Ну у неё всюду p=new char[1]; if(!p) {cout << "Ошибка выделения памяти \n"; exit(1);} Помоему задолбаться можно это приписывать при каждом выделении памяти. Добавлено позже: Вопрос на засыпку: а как удалить структуру (ну что мне писать в деструкторе в классе) ? Есть вот такая структура в классе и вот мой деструктор, который тоже в классе: --- Код: --- struct PRICE { char name[30];// название товара char shop[30];//;// название магазина double cost;// цена товара }; PRICE abc; ~Test() { cout<<"Дестуктор был запущен"; delete abc.cost; delete abc.name; delete abc.shop; } --- Конец кода --- Я так понимаю это я плохо придумал, но просто удалить структуру не получается (ну оно и не удивительно :) ), а если пробовать удалять по кускам то double элемент структуры удаляться не хочет с ошибкой: ||In destructor `Test::~Test()':| |27|error: type `double' argument given to `delete', expected pointer| Так всё же как в таких случаях поступать? |
| HoRRoR:
--- Цитата ---Ну у неё всюду --- Конец цитаты --- Тю блин, ты про это... Я думал, ты про проверку, выделена память через new или через malloc. Честно - я никогда не использую, но вообще осторожность лишней не бывает. --- Цитата ---Вопрос на засыпку: а как удалить структуру (ну что мне писать в деструкторе в классе) ? --- Конец цитаты --- Эээ... А ничего, что удалять можно только выделенные блоки памяти? о_О Причём только через указатель, полученный при выделении. А ты пытаешься кусок памяти внутри выделенного куска (и то при условии, что объект Test у тебя создаётся через new), да ещё и передавая не указатели, а переменные о_О Вообще глупость, в общем... Чтобы удалить структуру, ты сперва должен её создать сам. |
| gepar:
HoRRoR,ну у меня тут по умолчанию вместе с классом всегда создаётся и структура abc (PRICE abc) под которую и выделяется там место - два массива по 30 элементов и один элемет double, допустим что их инициализацию мы тоже провели и её то (структуру) теперь и надо удалить так как больше из данных класс ничего не имеет, ну static элементы есть, но они общие. Как мне поступить посоветуй. Я понял что я пробую глупо её удалить, но как тогда иначе поступить? |
| HoRRoR:
Зачем тебе её удалять? В чём смысл? При удалении объекта класса она сама удалится. В твоём примере ты пытаешься удалить её в деструкторе, что вообще лишено смысла - после деструктора она сама удалится. А если уж действительно накладно её хранить - то создавай и удаляй её сам: --- Код: ---PRICE *abc; Test() { abc = new PRICE; } void foo() { ... delete abc; ... } --- Конец кода --- |
| gepar:
HoRRoR,а я с самого начала так попробовал, пишет \7\4.cpp||In destructor `Test::~Test()':| \7\4.cpp|27|error: type `struct Test::PRICE' argument given to `delete', expected pointer| У меня же сейчас опять же таки важно не то чтобы это было красиво /логично/удобно, а то чтобы в программе был деструктор :) Это как и с той же структурой запихнутой в класс - непонятно зачем, но надо. Вот и здесь так, я там дальше тоже извращался с конструктором по умолчанию чтобы он хоть что-то делал лишь бы он был. На всякий случай код программы полностью: --- Код: ---//Программа создаёт структру, запрашивает данные для её заполнения после //чего производит поиск по структуре введённых данных # include <iostream> # include <iomanip> # include <windows.h> using namespace std; const int size=3; class Test { public: Test() { numberOfClass++; } Test(Test &right) { abc=right.abc; } ~Test() { cout<<"Дестуктор был запущен"; delete abc; } void setName(char a[]) { strcpy(abc.name,a); } void setShop(char a[]) { strcpy(abc.shop,a); } char *getShop() { return abc.shop; } void setCost(double a) { if (a>0) abc.cost=a; else { cout<<"Введена направильная цена, цена установлена в 1\n"; abc.cost=1; } } void search(char a[]) // Ищет есть ли в структуре элементы с нужным нам именем { if (!(strcmp(a,abc.name))) { cout<<"Нужный вам товар есть в магазине "<<abc.shop <<"\nЕго цена составляет: "<<abc.cost<<" грн"<<"\n\n"; resultOfSeach=1; }; } static int searchs() { return resultOfSeach;//Возвращает результат поисков } static int numberOfClass; private: struct PRICE { char name[30];// название товара char shop[30];//;// название магазина double cost;// цена товара }; PRICE abc; static int resultOfSeach;// Нужна чтобы знать был ли найден товар для хоть одного класса }; int Test::resultOfSeach=0; int Test::numberOfClass=0; int main() { setlocale(LC_ALL, "Russian"); char search[30]; char temp[30]; int result=0; double cost; int n; cout<<"Введите колличество магазинов: "; cin>>n; Test *a=new Test [n]; for (int i=0;i<n;i++) { cout<<"-----Магазин N"<<i+1<<"-----\n"; cout<<"Введите название товара: "; cin>>temp; a[i].setName(temp); cout<<"Введите название магазина:"; cin>>temp; a[i].setShop(temp); cout<<"Введите цену товара :"; cin>>cost; a[i].setCost(cost); } cout<<"\nВведите имя интересущего вас товара: "; cin>>search; for (int i=0;i<n;i++) a[i].search(search); if (!(a[0].searchs())) cout<<"Указанный товар в магазинах не найден\n"; Test b=a[0]; delete a; cout<<"\nКонструктор копии работает и мы можем увидеть название магазина N1\nдаже после удаления оригинала a: "<<b.getShop()<<'\n'; cout<<"Всего было магазинов: "<<Test::numberOfClass<<'\n'; system("pause"); return EXIT_SUCCESS; } --- Конец кода --- Вообще можешь и не читать полнсотью, надо только чтобы деструктор удалил саму структуру. |
| HoRRoR:
--- Цитата ---HoRRoR,а я с самого начала так попробовал, пишет --- Конец цитаты --- Перечитай ещё раз мой код и вчитайся в текст ошибки. Ты не так пробовал. И вообще, глупость неимоверная - париться насчёт удаления текстуры, которая создаётся и удаляется автоматически. |
| gepar:
HoRRoR,перечитал и всё равно не могу уловить твою идею. Ну пытаюсь сделать конструктор как у тебя и тогда получаю \7\4.cpp||In constructor `Test::Test()':| \7\4.cpp|16|error: no match for 'operator=' in '((Test*)this)->Test::abc = (Test::PRICE*)operator new(72u)'| \7\4.cpp|77|note: candidates are: Test::PRICE& Test::PRICE::operator=(const Test::PRICE&)| Какая-то страшная ошибка. |
| HoRRoR:
Да твою мать, перечитай ещё раз! Указатель там, а не структура! new может возвращать только указатель. |
| gepar:
HoRRoR, не сердись :) Там просто другая проблема возникает (ну помимо того что надо всюду делать операцию стрелка) с контруктором копии... если оставить всё как есть в прошлом коде то тогда он будет указывать на тот же участок памяти (ну и при повторном удалении конечно же будет ошибка), хотя я уже исправил и теперь программа выглядит так: --- Код: ---//Программа создаёт структру, запрашивает данные для её заполнения после //чего производит поиск по структуре введённых данных # include <iostream> # include <iomanip> # include <windows.h> using namespace std; const int size=3; class Test { public: Test() { abc = new PRICE; numberOfClass++; } Test(Test &right) { abc= new PRICE; strcpy(abc->name,right.abc->name); strcpy(abc->shop,right.abc->shop); abc->cost=right.abc->cost; } ~Test() { cout<<"Дестуктор был запущен"; delete abc; } void setName(char a[]) { strcpy(abc->name,a); } void setShop(char a[]) { strcpy(abc->shop,a); } char *getShop() { return abc->shop; } void setCost(double a) { if (a>0) abc->cost=a; else { cout<<"Введена направильная цена, цена установлена в 1\n"; abc->cost=1; } } void search(char a[]) // Ищет есть ли в структуре элементы с нужным нам именем { if (!(strcmp(a,abc->name))) { cout<<"Нужный вам товар есть в магазине "<<abc->shop <<"\nЕго цена составляет: "<<abc->cost<<" грн"<<"\n\n"; resultOfSeach=1; }; } static int searchs() { return resultOfSeach;//Возвращает результат поисков } static int numberOfClass; private: struct PRICE { char name[30];// название товара char shop[30];//;// название магазина double cost;// цена товара }; PRICE *abc; static int resultOfSeach;// Нужна чтобы знать был ли найден товар для хоть одного класса }; int Test::resultOfSeach=0; int Test::numberOfClass=0; int main() { setlocale(LC_ALL, "Russian"); char search[30]; char temp[30]; int result=0; double cost; int n; cout<<"Введите колличество магазинов: "; cin>>n; Test *a=new Test [n]; for (int i=0;i<n;i++) { cout<<"-----Магазин N"<<i+1<<"-----\n"; cout<<"Введите название товара: "; cin>>temp; a[i].setName(temp); cout<<"Введите название магазина:"; cin>>temp; a[i].setShop(temp); cout<<"Введите цену товара :"; cin>>cost; a[i].setCost(cost); } cout<<"\nВведите имя интересущего вас товара: "; cin>>search; for (int i=0;i<n;i++) a[i].search(search); if (!(a[0].searchs())) cout<<"Указанный товар в магазинах не найден\n"; Test b=a[0]; delete a; cout<<"\nКонструктор копии работает и мы можем увидеть название магазина N1\nдаже после удаления оригинала a: "<<b.getShop()<<'\n'; cout<<"Всего было магазинов: "<<Test::numberOfClass<<'\n'; system("pause"); return EXIT_SUCCESS; } --- Конец кода --- ТЕ: в конструкторе копии я через strcpy построчно копирую все данные из одной структуры в другую, жаль что нельзя посредством присваивания как-то указать что нужно скопировать все данные из тех участков памяти, а не указывать на тот же участок. |
| HoRRoR:
--- Цитата ---Там просто другая проблема возникает (ну помимо того что надо всюду делать операцию стрелка) --- Конец цитаты --- А необходимость набирать код для тебя не проблема? --- Цитата ---если оставить всё как есть в прошлом коде то тогда он будет указывать на тот же участок памяти (ну и при повторном удалении конечно же будет ошибка) --- Конец цитаты --- А что тебе мешает написать конструктор копии, в котором ты будешь нормально создавать копию? --- Цитата ---жаль что нельзя посредством присваивания как-то указать что нужно скопировать все данные из тех участков памяти, а не указывать на тот же участок. --- Конец цитаты --- Можно. Структура скопируется полностью как надо, т.к. память здесь не выделяемая, а фиксированная. |
| gepar:
--- Цитата: HoRRoR ---А что тебе мешает написать конструктор копии, в котором ты будешь нормально создавать копию? --- Конец цитаты --- Так я же и написал его: --- Код: --- Test(Test &right) { abc= new PRICE; strcpy(abc->name,right.abc->name); strcpy(abc->shop,right.abc->shop); abc->cost=right.abc->cost; } --- Конец кода --- --- Цитата: HoRRoR ---Можно. Структура скопируется полностью как надо, т.к. память здесь не выделяемая, а фиксированная. --- Конец цитаты --- Нет, ну я же переделал по твоему совету чтобы был указатель abc (ну чтобы деструктору было чем заняться :) ) так что память теперь выделяемая. Хотя там программа то уже как видишь работает и в ней всё ок, а вот теперь мне надо переделать ту где динамическая структура (та которая двунаправленный список), вот в ней то и начинается всё интересное. Просто эта динам. структура (я ещё тогда переделал твой вариант вытянув все функции из структуры в класс и поправив указатели, в структуре лишь оставил конструктор по умолчанию) ведёт себя слегка странно. Вариант 1 всё работает хорошо: --- Код: ---#include <iostream> #include <cstring> using namespace std; class Test { public: struct ListItem; // Конструктор по умолчанию Test(string data) { abc=new ListItem(data); } // Печать списка void print_list() { ListItem* item = this->abc; while(item) { cout << item->data; item = item->next; if(item) cout << " "; } cout << endl; } // Удаляет первые символы в строках void assigned() { ListItem* item=this->abc; while (item) { item->data.assign(&item->data[1]); item=item->next; } } //Добавляет инвертированный список void plus_invert () { ListItem *item=this->getTail(); while (item) { this->addToTail(item->data); item = item->prev; } } ListItem* getTail() { ListItem* item = abc; while(item->next) item = item->next; return item; } ListItem* addToTail(const string data) { ListItem *item = new ListItem(data), *last = getTail(); item->prev = last; last->next = item; return item; } ListItem* findLastItem(const string data) { ListItem* item = abc, *last = NULL; while(item->next) { if(item->data == data) { last = item; } item = item->next; } return last; } bool insertAfterLastItem(const string data, Test list) { ListItem* last = findLastItem(data), *next_item, *prev_item, *list_last; if(!last) return false; next_item = last->next; list_last = getTail(); list_last->next = next_item; if(next_item) next_item->prev = list_last; list.abc->prev = last; last->next = list.abc; return true; } struct ListItem { string data; // Хранимые в элементе списка данные ListItem *prev, *next; // Указатели на предыдущий и следующий элементы // Конструктор ListItem(const string data):prev(NULL),next(NULL) { this->data = data; } ~ListItem() { if(next) delete next; } }; ListItem *abc; }; int main() { Test a("aa1"); a.addToTail("aa2"); a.addToTail("aa3"); a.addToTail("aa4"); cout << "List a: "; a.print_list(); Test b("bb1"); b.addToTail("bb2"); b.addToTail("bb3"); b.addToTail("bb4"); cout << "List b: "; b.print_list(); a.insertAfterLastItem("aa3", b); cout << "Merged: "; a.print_list(); a.assigned(); cout<<"After deleting first symbol: "; a.print_list(); a.plus_invert(); cout<<"After inverting (and append): "; a.print_list(); return 0; } --- Конец кода --- И тут я добавляю деструктор что удаляет мой указатель abc на структру ... --- Код: ---#include <iostream> #include <cstring> using namespace std; class Test { public: struct ListItem; // Конструктор по умолчанию Test(string data) { abc=new ListItem(data); } ~Test() { cout<<"Destructor runs"; delete abc; } // Печать списка void print_list() { ListItem* item = this->abc; while(item) { cout << item->data; item = item->next; if(item) cout << " "; } cout << endl; } // Удаляет первые символы в строках void assigned() { ListItem* item=this->abc; while (item) { item->data.assign(&item->data[1]); item=item->next; } } //Добавляет инвертированный список void plus_invert () { ListItem *item=this->getTail(); while (item) { this->addToTail(item->data); item = item->prev; } } ListItem* getTail() { ListItem* item = abc; while(item->next) item = item->next; return item; } ListItem* addToTail(const string data) { ListItem *item = new ListItem(data), *last = getTail(); item->prev = last; last->next = item; return item; } ListItem* findLastItem(const string data) { ListItem* item = abc, *last = NULL; while(item->next) { if(item->data == data) { last = item; } item = item->next; } return last; } bool insertAfterLastItem(const string data, Test list) { ListItem* last = findLastItem(data), *next_item, *prev_item, *list_last; if(!last) return false; next_item = last->next; list_last = getTail(); list_last->next = next_item; if(next_item) next_item->prev = list_last; list.abc->prev = last; last->next = list.abc; return true; } struct ListItem { string data; // Хранимые в элементе списка данные ListItem *prev, *next; // Указатели на предыдущий и следующий элементы // Конструктор ListItem(const string data):prev(NULL),next(NULL) { this->data = data; } ~ListItem() { if(next) delete next; } }; ListItem *abc; }; int main() { Test a("aa1"); a.addToTail("aa2"); a.addToTail("aa3"); a.addToTail("aa4"); cout << "List a: "; a.print_list(); Test b("bb1"); b.addToTail("bb2"); b.addToTail("bb3"); b.addToTail("bb4"); cout << "List b: "; b.print_list(); a.insertAfterLastItem("aa3", b); cout << "Merged: "; a.print_list(); a.assigned(); cout<<"After deleting first symbol: "; a.print_list(); a.plus_invert(); cout<<"After inverting (and append): "; a.print_list(); return 0; } --- Конец кода --- И получаю очень интересную картину... Если честно то у меня разрыв шаблона: я всегда думал что программа при попытке обратиться к памяти где данные другой программы то получит отказ, а оно во как. Добавлено позже: Ну как я понимаю у меня что-то не так с insertAfterLastItem (после её работы здесь такое начинается), но почему без написания моего деструктора проблем нет мне непонятно. И в итоге непонятно с insertAfterLastItem что-то не так или с деструктором что-то не так. Добавлено позже: Такс, нашёл одну из ошибок (я балда амперсант не поставил и там передавалась копия этой insertAfterLastItem вместо оригинала), но теперь программа не доходит до конца и после запуска деструктора зависает, притом зависает не всегда, а в процентах 70% o_0 Пытается освободить уже освобождённую память где-то чтоль? Так почему не каждый раз тогда зависает ... --- Код: ---#include <iostream> #include <cstring> using namespace std; class Test { public: struct ListItem; // Конструктор по умолчанию Test(string data) { abc=new ListItem(data); } ~Test() { cout<<"DESTRUCTOR RUNS\n"; delete abc; } // Печать списка void print_list() { ListItem* item = this->abc; while(item) { cout << item->data; item = item->next; if(item) cout << " "; } cout << endl; } // Удаляет первые символы в строках void assigned() { ListItem* item=this->abc; while (item) { item->data.assign(&item->data[1]); item=item->next; } } //Добавляет инвертированный список void plus_invert () { ListItem *item=this->getTail(); while (item) { this->addToTail(item->data); item = item->prev; } } ListItem* getTail() { ListItem* item = abc; while(item->next) item = item->next; return item; } ListItem* addToTail(const string data) { ListItem *item = new ListItem(data), *last = getTail(); item->prev = last; last->next = item; return item; } ListItem* findLastItem(const string data) { ListItem* item = abc, *last = NULL; while(item->next) { if(item->data == data) { last = item; } item = item->next; } return last; } bool insertAfterLastItem(const string data, Test &list) { ListItem* last = findLastItem(data), *next_item, *prev_item, *list_last; if(!last) return false; next_item = last->next; list_last = getTail(); list_last->next = next_item; if(next_item) next_item->prev = list_last; list.abc->prev = last; last->next = list.abc; return true; } struct ListItem { string data; // Хранимые в элементе списка данные ListItem *prev, *next; // Указатели на предыдущий и следующий элементы // Конструктор ListItem(const string data):prev(NULL),next(NULL) { this->data = data; } ~ListItem() { if(next) delete next; } }; ListItem *abc; }; int main() { Test a("aa1"); a.addToTail("aa2"); a.addToTail("aa3"); a.addToTail("aa4"); cout << "List a: "; a.print_list(); Test b("bb1"); b.addToTail("bb2"); b.addToTail("bb3"); b.addToTail("bb4"); cout << "List b: "; b.print_list(); a.insertAfterLastItem("aa3", b); cout << "Merged: "; a.print_list(); a.assigned(); cout<<"After deleting first symbol: "; a.print_list(); a.plus_invert(); cout<<"After inverting (and append): "; a.print_list(); return 0; } --- Конец кода --- Добавлено позже: Да что же это такое, я же деструктор то оставил в самой структуре и ему заняться нечем кроме как освобождения повторно памяти, во туплю сегодня. |
| HoRRoR:
--- Цитата ---Нет, ну я же переделал по твоему совету чтобы был указатель abc (ну чтобы деструктору было чем заняться ) так что память теперь выделяемая. --- Конец цитаты --- Аргх! --- Код: --- abc= new PRICE; *abc = *(right.abc); --- Конец кода --- --- Цитата ---Если честно то у меня разрыв шаблона: я всегда думал что программа при попытке обратиться к памяти где данные другой программы то получит отказ, а оно во как. --- Конец цитаты --- В смысле? Архитектура не даст тебе залезть в память другого приложения. |
| gepar:
HoRRoR,воот, а почему тогда уходил на печать список запущенных/установленных приложений, информация о процессоре (я картинку убрал так как теперь по контексту не подходит, но могу ещё раз прикрепить если ты её не видел) ? Добавлено позже: Кстати финальный результат моей работы: --- Код: ---#include <iostream> #include <cstring> using namespace std; class Test { public: struct ListItem; // Конструктор по умолчанию Test(string data) { abc=new ListItem(data); } ~Test() { cout<<"DESTRUCTOR RUNS\n"; delete abc; } Test(Test &right) { ListItem* item = right.abc; abc=new ListItem (item->data); item=item->next; while (item) { this->addToTail(item->data); item=item->next; } } // Печать списка void print_list() { ListItem* item = this->abc; while(item) { cout << item->data; item = item->next; if(item) cout << " "; } cout << endl; } // Удаляет первые символы в строках void assigned() { ListItem* item=this->abc; while (item) { item->data.assign(&item->data[1]); item=item->next; } } //Добавляет инвертированный список void plus_invert () { ListItem *item=this->getTail(); while (item) { this->addToTail(item->data); item = item->prev; } } ListItem* getTail() { ListItem* item = abc; while(item->next) item = item->next; return item; } ListItem* addToTail(const string data) { ListItem *item = new ListItem(data), *last = getTail(); item->prev = last; last->next = item; return item; } ListItem* findLastItem(const string data) { ListItem* item = abc, *last = NULL; while(item->next) { if(item->data == data) { last = item; } item = item->next; } return last; } bool insertAfterLastItem(const string data, Test &list) { ListItem* last = findLastItem(data), *next_item, *prev_item, *list_last; if(!last) return false; next_item = last->next; list_last = getTail(); list_last->next = next_item; if(next_item) next_item->prev = list_last; list.abc->prev = last; last->next = list.abc; return true; } struct ListItem { string data; // Хранимые в элементе списка данные ListItem *prev, *next; // Указатели на предыдущий и следующий элементы // Конструктор ListItem(const string data):prev(NULL),next(NULL) { this->data = data; } }; ListItem *abc; }; int main() { Test *a=new Test("aa1"); a->addToTail("aa2"); a->addToTail("aa3"); a->addToTail("aa4"); cout << "List a: "; a->print_list(); Test b("bb1"); b.addToTail("bb2"); b.addToTail("bb3"); b.addToTail("bb4"); cout << "List b: "; b.print_list(); a->insertAfterLastItem("aa3", b); cout << "Merged: "; a->print_list(); a->assigned(); cout<<"After deleting first symbol: "; a->print_list(); a->plus_invert(); cout<<"After inverting (and append): "; a->print_list(); Test c=*a; delete a; cout<<"After deleting a we still can see our elements,\nso constructor of copy work correct:\n"; c.print_list(); return 0; } --- Конец кода --- Теперь уже вылетов и ситуаций когда программа иногда виснет за счёт того что освобождает уже освобождённую память нет :) |
| DeniSS:
Это открытый урок? :D |
| gepar:
DeniSS,ага. HoRRoR лекции читает, у него это хорошо получается :) |
| HoRRoR:
--- Цитата ---HoRRoR,воот, а почему тогда уходил на печать список запущенных/установленных приложений, информация о процессоре (я картинку убрал так как теперь по контексту не подходит, но могу ещё раз прикрепить если ты её не видел) ? --- Конец цитаты --- А хрен знает. Мусор, наверное. Т.е. выделяется память под приложение - естественно, она не очищается. Далее, ты сам либо забываешь заменить данные на свои, либо же вылезаешь за пределы - т.е. внутри выделенной под приложение памяти затрагиваешь не выделенные участки памяти, которые до этого не были использованы программой, т.е. данные в них остались старые. А в них может быть что угодно - т.е. любые данные работы предыдущих программ или системы. Абстрактный пример - запустил ты программу, она записала в память "Hello World!". Закрыл программу, открыл твою - система распределила память так, что частично или полностью блок памяти, использовавшийся в первой программе, используется и в этой. В ней ты выделил память под строку, она волей случая совпала с началом "Hello World!". Далее у тебя какой-то сбой, при котором ты либо не туда пишешь свои данные, либо вовсе забываешь записать их в строку, но выводишь её. В результате, при выводе строки получаешь "Hello World!". Или же ты записываешь данные в строку, но при выводе что-то путаешь (вылезаешь за пределы) и попадаешь на "Hello World!". |
| gepar:
Читаю о наследовании и возник вопрос: вот есть у нас класс abc унаследовавший от xyz его функции, при этом в abc у нас есть функция void print() и в xyz у нас есть функция void print(). Есть main, которая тестирует наш новый класс abc и при вызове из main получается вызывается функция print() из abc, так? Если да то можно ли вызвать ту старую print() что была в xyz, ну мне так чисто интересно :) ? |
| Навигация |
| Главная страница сообщений |
| Следующая страница |
| Предыдущая страница |