Wektor przechowujący obiekty różnych typów.

0

Witajcie. Czy jest możliwość utworzenia wektora (ew. listy), który będzie mógł przechowywać obiekty różnych klas dziedziczących z jednej klasy bazowej? Gdy wektor będzie typu bazowego to niby się da, ale nie można wtedy wywołać funkcji klas pochodnych np:

//tworze sobie wektor klasy bazowej
vector<zwierze>zwie;
//wkładam do niego obiekty za pomocą konstruktorów różnych typów pochodnych
zwie.push_back(slon());
zwie.push_back(zajac());
zwie.push_back(ryba());
//i chciałbym użyć na nich ich własnych metod ale sie nie da bo funkcje nie należą do klasy bazowej
zwie[0].uzyjtraby();
zwie[1].skacz();
zwie[2].plywaj();

niestety nie da się utworzyć wektora typu auto

0

To podejście prowadzi donikąd. Równie dobrze możesz chcieć przechowywać w wektorze zupełnie niepowiązane ze sobą obiekty.

Możesz natomiast dodać do klasy bazowej jakąś metodę wirtualną, powiedzmy ruszaj(). Wtedy w każdej klasie pochodnej implementujesz ruszaj() na swój sposób, czyli np.

class slon {
    virtual void ruszaj() { uzyjtraby(); }
};
class zajac {
    virtual void ruszaj() { skacz(); }
};
0

Tak się nie da ponieważ klasy pochodne mogą być fizycznie większe niż bazowa.
Więc albo: vector<zwierze*> fauna;
albo: vector<shared_ptr<zwierze> > fauna;

0

Mogę dodać wszystkie funkcje klas pochodnych do klasy bazowej jako wirtualne, ale czy to będzie poprawne?

0

O ile ta wirtualna w bazowej będzie rzucać wyjątek - to całkiem znośne.

0

rzucać wyjątek? nie do końca rozumiem.

0
Krwawy Lew napisał(a):

Mogę dodać wszystkie funkcje klas pochodnych do klasy bazowej jako wirtualne, ale czy to będzie poprawne?

Czy każde zwierzę umie pływać? Czy każde umie użyć trąby?

0

no nie ale nie widzę innego sposobu. no chyba, że taki:

 vector<zwierze>zwie;

zwie.push_back(slon());
zwie.push_back(zajac());
zwie.push_back(ryba());

ryba *r=(ryba*)&zwie[2];
r->plywaj();

//pomijając że lepiej byłoby żeby wektor przechowywał wskaźniki

ale wtedy za każdym razem przy wywoływaniu funkcji musiałbym tworzyć wskaźnik

0

Przecież już ci powiedziano że tak się nie da.

0

ok ok, jeśli będzie ten sam rozmiar klas to sie da, to jest tylko przykład, wiem, że lepiej wektor ze wskaźnikami

0

Nawet przy takim samym rozmiarze się nie da ponieważ stracisz informacje który obiekt kim jest.

0

no dobrze, rozumiem, ale pomijając już te wskaźniki to co myślicie o tym rzutowaniu? Jest sens tak to robić?

0

ale jaki jest w ogóle sens czegoś takiego?
jeżeli chcesz wrzucać obiekty do wspólnej listy to powinna wystąpić jakaś abstrakcja i to znaczy że chcesz użyć jakiejś wspólnej cechy tych obiektów
metoda którą więc chcesz wtedy wywoływać powinna się nazywać tak samo

jeżeli nie ma żadnej abstrakcji to trzymaj te zwierzęta w osobnych wektorach

0

RTTI powinno być ostatnim rozwiązaniem problemu, nie jego pierwszym. Takim nie do końca ładnym hackiem. Znacznie lepiej jest zaprojektować hierarchie dziedziczenia z sensem.

0

Wielkie dzięki za wszystko. Mam jeszcze jedno pytanie. Klasa bazowa, której obiektu nie można utworzyć (czyli taka jak w moim przykładzie -zwierze) powinna być abstrakcyjna, prawda? Tylko, że wtedy nie można utworzyć wektora tej klasy nawet jeśli będzie się w nim przechowywało obiekty klas pochodnych.

0

Powiedz którego słowa nie rozumiesz w zdaniu: - "Nie ma możliwości przechowywania w wektorze różnych obiektów klas pochodnych."

0

chodziło mi o wskaźniki, mój błąd

1

Nie można utworzyć obiektu klasy abstrakcyjnej. A trzymać wskaźniki kto Ci zabrania?

0

no faktycznie, wcześniej musiałem zrobić coś źle bo wyświetlało błąd, dzięki

0
_13th_Dragon napisał(a):

Nawet przy takim samym rozmiarze się nie da ponieważ stracisz informacje który obiekt kim jest.

Przy wskaźnikach też tracę te informacje.

 
vector<zwierze*>zwie;

slon*s=new slon;
zwie.push_back(s);

zwie[0]->funkcjawirtualna(); //nie działa bo myśli że jest typem bazowym
cout << typeid (zwie[0]).name(); //wypisuje typ bazowy 
0

To widocznie coś spieprzyłeś przy nadpisywaniu tej funkcji.

typeid (zwie[0]).name()

zwie[0] jest typu zwierze* więc nie wiem czego się spodziewałeś

0

faktycznie, znalazłem błąd, dzięki

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