Co jest nie tak w moim kodzie? (kontener deque, iterator, polimorfizm)

0

Witam.
Możliwe że mi się miesza c++ z javą, więc proszę o pomoc przy polimorfiźmie.
Utworzyłem jedną klasę bazową "pojazd_mechaniczny" i dwie klasy pochodne dziedziczące po bazowej: samochod i motocykl.
Klasa samochod ma jeszcze swoje dodatkowe pola i metody.
Dodawanie obiektów chyba działa. Ale problem jest przy wyświetlaniu.
Obiekty trzymam w kontenerze deque<pojazd_mechaniczny>pojazd.
Dodaje obiekty w sposób pojazd.push_back(samochod()) lub pojazd.push_back(motocykl()). Przez new object() nie wchodzi.
Przy wyswietlaniu wszystkich obiektów typu samochod oraz motocykl w pętli for jest problem przy wyświetleniu obiektu który jest typu samchod. Obiekty motocykl nie mają żadnych dodatkowych pól i metod w porównaniu do obiektów typu samochod.
Funkcja wyswietlająca wszystkie dane o wszystkich obiektach wygląda tak:

void Wyswietl_dane_o_wszystkich_pojazdach()
{
	for(deque<pojazd_mechaniczny>::iterator i=pojazd.begin();i!=pojazd.end();i++)
    {
    	cout<<"Marka: "<<i->zwroc_marke()<<endl
    	<<"Model: "<<i->zwroc_model()<<endl
    	<<"Rok produkcji: "<<i->zwroc_rok_produkcji()<<endl
    	<<"Moc: "<<i->zwroc_moc()<<" KM"<<endl
    	<<"Rodzaj paliwa: "<<i->zwroc_rodzaj_paliwa()<<endl
    	<<"Pojemnosc baku: "<<i->zwroc_pojemnosc_baku()<<" litrow"<<endl
    	<<"Maksymalna predkosc: "<<i->zwroc_max_predkosc()<<"km/h"<<endl
    	<<"Liczba miejsc: "<<i->zwroc_liczbe_miejsc()<<endl
    	<<"Wysokosc: "<<i->zwroc_wysokosc()<<" cm"<<endl
    	<<"Dlugosc: "<<i->zwroc_dlugosc()<<" cm"<<endl
    	<<"Szerokosc: "<<i->zwroc_szerokosc()<<" cm"<<endl
    	<<"Waga: "<<i->zwroc_wage()<<" kg"<<endl;
    	if(typeid(samochod)==typeid(i))
    	{
	 	cout<<"Liczba drzwi: "<<i->zwroc_liczbe_drzwi()<<endl
    		<<"Pojemnosc bagaznika: "<<i->zwroc_pojemnosc_bagaznika()<<" litrow"<<endl;
		}
    }
}

I chodzi o sprawdzenie czy obiekt pojazd nie jest obiektem samochod. W Javie było coś takiego jak "if(a instanceof b){kod....}", a jak tu jest jeszcze przy użyciu iteratorów?

2

Naginasz zasadę podstawienia Liskov.
WyswietlDane() powinno być wirtualną metodą w klasie bazowej, a w razie czego powinno być nadpisywane przez potomków (właśnie gdy dorzucają coś od siebie, np. pojemność bagażnika).

1

typeid(samochod)==typeid(i) bzdura, i zawsze będzie iteratorem.

Masz deque<pojazd_mechaniczny>, więc wszystkie klasy dziedziczące z pojazd_mechaniczny zostaną do niego skonwertowane i w takiej postaci dodane. Musisz użyć wskaźników (tutaj pewnie unique_ptr)

1

O tej zasadzie podstawiania Liskov nie słyszałem jeszcze. Ale dzięki. Przyzwyczajenie z Javy gdzie coś takiego ktoś na jakimś kursie stosował.

3

new object() - zwraca typ (object *), który bez specjalnego operatora, który coś zrobi nie będzie działał jako argument w deque<pojazd_mechaniczny>::push_back.
Tym operatorem jest * (np. ptr), tylko w takim przypadku: pojazd.push_back((new samochod())); robisz memory leaka, bo nigdzie nie zapisujesz gdzie dany obszar pamięci został przydzielony.
Mógłbyś zrobić po prostu:

samochod *samochod_ptr = new samochod();
pojazd.push_back(*samochod_ptr);
delete samochod;
 

Tylko pytanie po co? Możesz bez problemu to zrobić bez wskaźników, w taki sposób:

 
pojazd.push_back(samochod());

Jednak, twój kontener trzyma obiekt, a nie wskaźnik na obiekt. Przez to polimorfizm tutaj nie działa, ponieważ wszystkie obiekty i tak są typu pojazd_mechaniczny. Jeśli do push_back dostarczysz obiekt pochodny, wtedy do kontenera i tak zostaną skopiowane dane z klasy bazowej, a z pochodnej nie będą brane pod uwagę.

Co do wyświetlania danych, możesz to zrobić właściwie na kilka sposobów, jednakże prawdopodobnie najlepszy bazuje na metodach wirtualnych.
Możesz to zrobić tak:

 

deque<pojazd_mechaniczny *> pojazd;

class pojazd_mechaniczny
{
public:
 // ...
 virtual void wyswietl_dane()
 {
   cout<<"Marka: "<<zwroc_marke()<<endl
       <<"Model: "<<zwroc_model()<<endl
       <<"Rok produkcji: "<<zwroc_rok_produkcji()<<endl
       <<"Moc: "<<zwroc_moc()<<" KM"<<endl
       <<"Rodzaj paliwa: "<<zwroc_rodzaj_paliwa()<<endl
       <<"Pojemnosc baku: "<<zwroc_pojemnosc_baku()<<" litrow"<<endl
       <<"Maksymalna predkosc: "<<zwroc_max_predkosc()<<"km/h"<<endl
       <<"Liczba miejsc: "<<zwroc_liczbe_miejsc()<<endl
       <<"Wysokosc: "<<zwroc_wysokosc()<<" cm"<<endl
       <<"Dlugosc: "<<zwroc_dlugosc()<<" cm"<<endl
       <<"Szerokosc: "<<zwroc_szerokosc()<<" cm"<<endl
       <<"Waga: "<<zwroc_wage()<<" kg"<<endl;
 }
};

class samochod : public pojazd_mechaniczny
{
public:
 // ...
 virtual void wyswietl_dane() override
 {
  pojazd_mechaniczny::wyswietl_dane();
  cout<<"Liczba drzwi: "<<zwroc_liczbe_drzwi()<<endl
      <<"Pojemnosc bagaznika: "<<zwroc_pojemnosc_bagaznika()<<" litrow"<<endl;
 }
};

class motocykl : public pojazd_mechaniczny
{
public:
 // ...
 virtual void wyswietl_dane() override
 {
  pojazd_mechaniczny::wyswietl_dane();
  //cout<<"";
 }
};

void Wyswietl_dane_o_wszystkich_pojazdach()
{
    for(deque<pojazd_mechaniczny *>::iterator i=pojazd.begin();i!=pojazd.end();i++)
    {
        (*i)->wyswietl_dane();
    }
}

// dodawanie do pojazdow:
pojazd.push_back(new samochod()); // musisz zwolnić pamięć przed wyczyszczeniem, inaczej będzie memory leak.
0

Dodanie override pomogło.

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