Ĺadny brzuch
Mam pytanie. W takim kodzie
//main.cpp #include <iostream> #include "dane.h" using namespace std; int main(int argc, char *argv[]) { info q; q.wypelnij(); q.wypisz(); //info *t; //t = new info; //t->nazwa="ggg"; //t->ile=5; ///zapisuj.push_back(t); //for(pos=zapisuj.begin();pos!=zapisuj.end();++pos) // cout << *pos ; } //dane.h #include <unistd.h> #include <string> #include <list> class info{ info *x, *y; public: info(); ~info(); std::string nazwa; int ile; void wypelnij(); bool zapisz(int fd, const void *data, size_t size); bool zapisz_nagl(int fd); void wypisz(); }; std::list<info*> czytaj; std::list<info*> zapisuj; std::list<info*>::iterator pos; info::info() { //wypelnij(); } info::~info() { delete x; delete y; } bool info::zapisz(int fd, const void *data, size_t size) { ... } bool info::zapisz_nagl(int fd) { ... } void info::wypelnij() { x = new info; x->nazwa="jakas nazwa"; x->ile=11; y = new info; y->nazwa="inna nazwa"; y->ile=10; zapisuj.push_back(x); zapisuj.push_back(y); } void info::wypisz() { for(pos=zapisuj.begin();pos!=zapisuj.end();++pos) std::cout << *pos << std::endl; }
gdy go skompiluje i uruchomie dostaję
0x503010
0x503070
czyli pewnie komórki pamięci. Pytanie dlaczego?
Gdy w main.cpp odkomentuje reszte linijek, to dostaję segvaulta. Też mnie ciekawi, dlaczego.
O czym bym musiał doczytać, bo to już nie pierwszy taki mój problem :|
Widze, że muszę odświeżyć własny topic ;)
Jeżeli w powyższym kodzie zmienie na
std::list<info> zapisuj; ... void info::wypelnij() { info x;//= new info; x.nazwa="jakas nazwa"; x.ile=11; info y;// = new info; y.nazwa="inna nazwa"; y.ile=10; zapisuj.push_back(x); zapisuj.push_back(y); } void info::wypisz() { for(pos=zapisuj.begin();pos!=zapisuj.end();++pos) std::cout << pos->nazwa << std::endl; }
To wszystko ładnie chodzi. Jednak chciałbym wiedziec, jak zrobić to samo dla std::list<info*> - na wskaźnikach. Na inym forum dostałem odpowiedz
pos jest iteratorem listy elementow typu "wskaźnik na info". Podanie coutowi "wskaźnika na info" efektuje wypisaniem adresu wskazywanego elementu., ale niestety nie wiem, jakbym miał to zapisać, aby chodziło.
No to tak:
Na innym forum mają rację :) i jak *pos daje wskaźnik na info to *(*pos) da Ci to na co wskazuje wskaźnik na info... względem kodu z pierwszego postu używając iteratora ( w taki sposób *(*pos)) musisz pamiętać o przeciążeniu operatora<< bo w końcu strumień cout otrzyma do wyświetlenia obiekt typu info, a tego niepotrafi... łączenie kod dane.h wygląda tak://dane.h, a main.cpp bez zmiann #include <unistd.h> #include <string> #include <list> class info{ info *x, *y; public: info(); ~info(); std::string nazwa; int ile; void wypelnij(); bool zapisz(int fd, const void *data, size_t size); bool zapisz_nagl(int fd); void wypisz(); friend std::ostream & operator<<(std::ostream & os, const info & in); }; std::ostream & operator<<(std::ostream & os, const info & in) { os << in.nazwa << " " << in.ile; return os; } std::list<info*> czytaj; std::list<info*> zapisuj; std::list<info*>::iterator pos; info::info() { //wypelnij(); } info::~info() { delete x; delete y; } bool info::zapisz(int fd, const void *data, size_t size) { } bool info::zapisz_nagl(int fd) { } void info::wypelnij() { x = new info; x->nazwa="jakas nazwa"; x->ile=11; y = new info; y->nazwa="inna nazwa"; y->ile=10; zapisuj.push_back(x); zapisuj.push_back(y); } void info::wypisz() { for(pos=zapisuj.begin();pos!=zapisuj.end();++pos) std::cout << *(*pos) << std::endl; }
A jeżeli nie chcesz przeciążać operatora to możesz też dostać się tak do zmiennych w klasie:
std::cout << (*pos)->nazwa << std::endl; std::cout << (*pos)->ile << std::endl;
Edit// Sprawdziłem jeszcze ... po usunięciu komentarzy z main i poprawieniu wypisywania przy iteratorze też działa.
Użytkownik reVis edytował ten post 11 lipiec 2006, 20:36
Dzięki, o to chodziło.
_____
A tak jeszcze przy okazji się zapytam, czy jest różnica w dwóch poniższych destruktorach?
info::~info() { delete x; delete y; }
a
info::~info() { delete this->x; delete this->y; }
Ja w powyższej klasie użyłem 1. wersji, bo ta mi się wydawała odpowiednia, ale gdzieś na necie widziałem ostatnio zapis z wersji 2. Także czy te definicje są sobie tożsame w tym przykładzie?
Pomiędzy tymi zapisamie nie ma żadnej różnicy. W jednym tylko jawnie korzystasz z this, wskaźnika na elementy danego egzemplarza klasy (każda klas taki posiada). Mógłbyś też pisać np:
void info::wypelnij() { this->x = new info; this->x->nazwa="jakas nazwa"; this->x->ile=11; this->y = new info; this->y->nazwa="inna nazwa"; this->y->ile=10; zapisuj.push_back(x); zapisuj.push_back(y); }
Ok, jeszcze raz dzięki.
zanotowane.pl doc.pisz.pl pdf.pisz.pl zsf.htw.pl
//main.cpp #include <iostream> #include "dane.h" using namespace std; int main(int argc, char *argv[]) { info q; q.wypelnij(); q.wypisz(); //info *t; //t = new info; //t->nazwa="ggg"; //t->ile=5; ///zapisuj.push_back(t); //for(pos=zapisuj.begin();pos!=zapisuj.end();++pos) // cout << *pos ; } //dane.h #include <unistd.h> #include <string> #include <list> class info{ info *x, *y; public: info(); ~info(); std::string nazwa; int ile; void wypelnij(); bool zapisz(int fd, const void *data, size_t size); bool zapisz_nagl(int fd); void wypisz(); }; std::list<info*> czytaj; std::list<info*> zapisuj; std::list<info*>::iterator pos; info::info() { //wypelnij(); } info::~info() { delete x; delete y; } bool info::zapisz(int fd, const void *data, size_t size) { ... } bool info::zapisz_nagl(int fd) { ... } void info::wypelnij() { x = new info; x->nazwa="jakas nazwa"; x->ile=11; y = new info; y->nazwa="inna nazwa"; y->ile=10; zapisuj.push_back(x); zapisuj.push_back(y); } void info::wypisz() { for(pos=zapisuj.begin();pos!=zapisuj.end();++pos) std::cout << *pos << std::endl; }
gdy go skompiluje i uruchomie dostaję
0x503010
0x503070
czyli pewnie komórki pamięci. Pytanie dlaczego?
Gdy w main.cpp odkomentuje reszte linijek, to dostaję segvaulta. Też mnie ciekawi, dlaczego.
O czym bym musiał doczytać, bo to już nie pierwszy taki mój problem :|
Widze, że muszę odświeżyć własny topic ;)
Jeżeli w powyższym kodzie zmienie na
std::list<info> zapisuj; ... void info::wypelnij() { info x;//= new info; x.nazwa="jakas nazwa"; x.ile=11; info y;// = new info; y.nazwa="inna nazwa"; y.ile=10; zapisuj.push_back(x); zapisuj.push_back(y); } void info::wypisz() { for(pos=zapisuj.begin();pos!=zapisuj.end();++pos) std::cout << pos->nazwa << std::endl; }
To wszystko ładnie chodzi. Jednak chciałbym wiedziec, jak zrobić to samo dla std::list<info*> - na wskaźnikach. Na inym forum dostałem odpowiedz
pos jest iteratorem listy elementow typu "wskaźnik na info". Podanie coutowi "wskaźnika na info" efektuje wypisaniem adresu wskazywanego elementu., ale niestety nie wiem, jakbym miał to zapisać, aby chodziło.
No to tak:
Na innym forum mają rację :) i jak *pos daje wskaźnik na info to *(*pos) da Ci to na co wskazuje wskaźnik na info... względem kodu z pierwszego postu używając iteratora ( w taki sposób *(*pos)) musisz pamiętać o przeciążeniu operatora<< bo w końcu strumień cout otrzyma do wyświetlenia obiekt typu info, a tego niepotrafi... łączenie kod dane.h wygląda tak://dane.h, a main.cpp bez zmiann #include <unistd.h> #include <string> #include <list> class info{ info *x, *y; public: info(); ~info(); std::string nazwa; int ile; void wypelnij(); bool zapisz(int fd, const void *data, size_t size); bool zapisz_nagl(int fd); void wypisz(); friend std::ostream & operator<<(std::ostream & os, const info & in); }; std::ostream & operator<<(std::ostream & os, const info & in) { os << in.nazwa << " " << in.ile; return os; } std::list<info*> czytaj; std::list<info*> zapisuj; std::list<info*>::iterator pos; info::info() { //wypelnij(); } info::~info() { delete x; delete y; } bool info::zapisz(int fd, const void *data, size_t size) { } bool info::zapisz_nagl(int fd) { } void info::wypelnij() { x = new info; x->nazwa="jakas nazwa"; x->ile=11; y = new info; y->nazwa="inna nazwa"; y->ile=10; zapisuj.push_back(x); zapisuj.push_back(y); } void info::wypisz() { for(pos=zapisuj.begin();pos!=zapisuj.end();++pos) std::cout << *(*pos) << std::endl; }
A jeżeli nie chcesz przeciążać operatora to możesz też dostać się tak do zmiennych w klasie:
std::cout << (*pos)->nazwa << std::endl; std::cout << (*pos)->ile << std::endl;
Edit// Sprawdziłem jeszcze ... po usunięciu komentarzy z main i poprawieniu wypisywania przy iteratorze też działa.
Użytkownik reVis edytował ten post 11 lipiec 2006, 20:36
Dzięki, o to chodziło.
_____
A tak jeszcze przy okazji się zapytam, czy jest różnica w dwóch poniższych destruktorach?
info::~info() { delete x; delete y; }
a
info::~info() { delete this->x; delete this->y; }
Ja w powyższej klasie użyłem 1. wersji, bo ta mi się wydawała odpowiednia, ale gdzieś na necie widziałem ostatnio zapis z wersji 2. Także czy te definicje są sobie tożsame w tym przykładzie?
Pomiędzy tymi zapisamie nie ma żadnej różnicy. W jednym tylko jawnie korzystasz z this, wskaźnika na elementy danego egzemplarza klasy (każda klas taki posiada). Mógłbyś też pisać np:
void info::wypelnij() { this->x = new info; this->x->nazwa="jakas nazwa"; this->x->ile=11; this->y = new info; this->y->nazwa="inna nazwa"; this->y->ile=10; zapisuj.push_back(x); zapisuj.push_back(y); }
Ok, jeszcze raz dzięki.