Niezrozumiałe zachowanie list

0

W klasie mam pole typu list. Deklaruję je w taki sposób:

list <Pociagi*>pociagi;

Później w programie dodaję elementy za pomocą metody push.back(); Zaraz po dodaniu danego elementu do listy wywołuję metodę, której zadaniem jest wylistować wszystkie dodane elementy. Gdy dodaję jeden pociąg - wszystko jest dobrze. Gdy dodaję kolejny - nagle obydwa elementy są takie same (tak jakby pierwszy się zmieniał). Ktoś wie dlaczego?
I pytanie nr 2. - jeżeli wywołuję metodę listującą wszystkie elementy zaraz po dodaniu nowego, wszystko ładnie się drukuje. Jednak gdy zachce mi się wywołać tę metodę w innym miejscu - wywala mi błąd "Access violation reading location 0xcccccccc". Pytanie takie samo - czemu?
Dodam tylko, że już mnie jasny szlag z tym trafia, bo w tym samym projekcie mam drugą, bliźniaczo podobną klasę, z tą różnicą, że tam elementami listy nie są wskaźniki, a obiekty i, o dziwo, w tamtej klasie wszystko listuje się poprawnie w każdym miejscu programu.
Metoda listująca wygląda tak:

void Pociag_Manager::listuj_pociagi(){
	if(pociagi.size() == 0){
		cout<<"brak pociagow"<<endl;
	}
	else{
		for(it = this->pociagi.begin(); it != this->pociagi.end(); it++){
			(*it)->drukuj_pociag();
		}
	}
}
0

pytanie nr 1.
prawdopodobnie robisz coś w stylu:
pociąg=pociąg1
dodajpociąg(pociąg)
pociag=pociag2
dodajpociąg(pociag)

wtedy masz listę (pociąg, pociąg), z tym że te nazwy pociąg to tylko "wskaźniki" na obiekty pociąg (czyli masz listę wskaźników). W rzeczywistosci po ostatniej linii tego pseudokodu oba wskaźniki pokazuja na ten sam obiekt - pociag2.

0
odpad napisał(a):

pytanie nr 1.
prawdopodobnie robisz coś w stylu:
pociąg=pociąg1
dodajpociąg(pociąg)
pociag=pociag2
dodajpociąg(pociag)

wtedy masz listę (pociąg, pociąg), z tym że te nazwy pociąg to tylko "wskaźniki" na obiekty pociąg (czyli masz listę wskaźników). W rzeczywistosci po ostatniej linii tego pseudokodu oba wskaźniki pokazuja na ten sam obiekt - pociag2.

Stworzyłem sobie klasę Manager, w której jest metoda dodaj_pociag i wygląda to w ten sposób, że najpierw wczytywane są dane, potem tworzony jest obiekt typu Pociag_osobowy pociag, wywoływana metoda push_back() z argumentem &pociag i tyle. W jaki sposób zapobiec temu dublowaniu wskaźników w liście? Próbowałem zrobić to tak:

Pociag_osobowy pociag(numer, nazwa, przewoznik, &stacja_p, &stacja_k, opoznienie, ilosc_pasazerow);
pom = &pociag;
this->pociagi.push_back(pom);
pom = NULL;

albo

Pociag_osobowy pociag(numer, nazwa, przewoznik, &stacja_p, &stacja_k, opoznienie, ilosc_pasazerow);
pom = &pociag;
this->pociagi.push_back(pom);
delete pom;

ale wtedy program staje na delete.

0

w tym momencie:
this->pociagi.push_back(pom);
dodajesz do listy wskaźnik (czy tam referencję) do pociągu. powinieneś dodać nie wskaźnik, tylko pociąg. Jak to powinieneś robić w C++ to Ci nie powiem (nie znam za bardzo tego języka), kombinowałbym coś takiego:
this->pociagi.push_back(*pom);
tyle że wtedy musiałbyś mieć listę obiektów, nie wskaźników

0
odpad napisał(a):

w tym momencie:
this->pociagi.push_back(pom);
dodajesz do listy wskaźnik (czy tam referencję) do pociągu. powinieneś dodać nie wskaźnik, tylko pociąg. Jak to powinieneś robić w C++ to Ci nie powiem (nie znam za bardzo tego języka), kombinowałbym coś takiego:
this->pociagi.push_back(*pom);

pom jest typu Pociag*, czyli przypisując pom = &pociag; ustawiam wskaźnik pom na komórkę pamięci zajmowaną przez pociag, a ponieważ jest to lista wskaźników a nie obiektów to tak musi być :-). Nie mogę zrobić z tego listy obiektów, bo po klasie Pociag dziedziczą klasy Pociag_osobowy i Pociag_towarowy, które korzystają z polimorfizmu, więc jakbym zrobił listę obiektów, to wszystko by się posypało :-)

0

Po jaką cholere dodajesz wskaźniki do listy? Zasada jest taka, że jak czegoś nie rozumiesz to nie używaj.
zrób sobie po prostu: list<Pociag> i nie będziesz mieć żadnych problemów. Wciskasz te wskaźniki wszędzie na siłę nawet jak nie są potrzebne.

z czym jest problem w Twoim kodzie? Z tym, że zupełnie nie wiesz co to jest stos. Dodajesz do listy adres obiektu, po czym go usuwasz (obiekt), a następnie w momencie gdy obiekt ściągany jest ze stosu wywoływany jest ponownie destruktor na nieistniejącym obiekcie. Błąd na błędzie. Ucz się, później pisz!

0

Walisz jak człowiek:

this->pociagi.push_back(new PociagOsobowy(numer, nazwa, przewoznik, &stacja_p, &stacja_k, opoznienie, ilosc_pasazerow));
0
krwq napisał(a):

Po jaką cholere dodajesz wskaźniki do listy? Zasada jest taka, że jak czegoś nie rozumiesz to nie używaj.
zrób sobie po prostu: list<Pociag> i nie będziesz mieć żadnych problemów. Wciskasz te wskaźniki wszędzie na siłę nawet jak nie są potrzebne.

Edytowałem wcześniej, ale widocznie nie zauważyłeś - nie mogę zrobić listy obiektów, bo dodaje do niej obiekty, które dziedziczą po klasie bazowej i korzystają z polimorfizmu. Jeżeli będę miał listę obiektów, to np. metoda drukuj_pociag() wywoła się ("o dziwo!") z klasy Pociag, a nie Pociag_osobowy... Chyba, że da się to napisać inaczej?

krwq napisał(a):

Błąd na błędzie. Ucz się, później pisz!

Och, uwielbiam takie komentarze! Bo przecież najlepszą metodą nauki wcale nie jest praktyka... Nie piszę w C++ na co dzień. Nie lubię tego języka, uważam, że jest niepraktyczny i źle mi się go używa. Niestety, jestem zmuszony w nim pisać, więc piszę. A forum chyba jest od tego, żeby jak się człowiek zatnie, to ktoś mu pomógł, hmm? :-)

Ma ktoś pomysł a propos pytania nr. 2? Ja swój zasób wyczerpałem...

1 użytkowników online, w tym zalogowanych: 0, gości: 1