Wskaznik Polimorficzny

0

Witam. Dzisiejszy problem do rozwiązania na początek dnia :). Wyobraźmy sobie następującą sytuację:

Mamy Abstrakcyjna klasę Osoba po której dziedziczą inne.

  • Chce decydować czy dodajemy Pracownika czy Studenta. Tworze:
    • wskaźnik użytkownik, którym będziemy wskazywać.
    • dwie listy typu wektor przechowujące wskaźniki na obiekty
    • pomocnicze obiekty s i p które będziemy dodawać na listy
  1. Nie wiem czy to dobry pomysł ale w ten sposob dodaje na liste wybrany obiekt. Musiałem wczesniej utworzyc dwie listy typu wektor przechowujące wskaźniki na obiekty, aby to zadziałało.
  listaPracownikow.push_back(dynamic_cast<Pracownik*>(uzytkownik)); // do odpowiedniej tablicy wrzucamy to na co wskazuje wskaznik

-Teraz chciałbym w zależności od sterowania wybrać liste do wyswietlenia. Tworze zatem:
+ vector <Osoba*> *lista; // wskaznikiem chce pokazywac na wybrana liste
+ funkcje Wyswietl
Przy probie wyświetlenia wyrzuca mi błąd

 Wyswietl(dynamic_cast< vector <Pracownik*> >(lista)); // BLAD!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

error: cannot dynamic_cast 'lista' (of type 'class std::vector<Osoba*>*') to type 'class std::vector<Pracownik*>' (target is not pointer or reference)|

class Osoba
{
public:
    Osoba() {};
    virtual void CzystoWirtualna()=0;
};
//*******************************************************************************
class Student : public Osoba
{
public:
    Student() {};
    virtual void CzystoWirtualna() {};
};
//*******************************************************************************
class Pracownik : public Osoba
{
public:
    Pracownik() {};
    virtual void CzystoWirtualna() {};
};
//*******************************************************************************

void Wyswietl(vector<Osoba*> lista) // lista studentow albo pracownikow
{
    //Wyswietlanie informacji
}

int main()
{
    Pracownik p;
    Student s;
    Osoba *uzytkownik;   // polimorficzny wskaznik

    vector <Pracownik*> listaPracownikow;
    vector <Student*>   listaStudentow;

//////////////// WYBIERZ KOGO DODAC DO JAKIEJ LISTY  //////////////
    int nr;
    cin >> nr;
    if(nr==1)
    {
        uzytkownik = &p;         // ustawienie wskaznika na pracownika
        listaPracownikow.push_back(dynamic_cast<Pracownik*>(uzytkownik)); //do odpowiedniej tablicy wrzucamy to na co wskazuje wskaznik
    }
    else
    {
        uzytkownik = &s;         // ustawienie wskaznika na pracownika
        listaStudentow.push_back(dynamic_cast<Student*>(uzytkownik));
    }

////////////// WYBIERZ LISTE DO WYSWIETLENIA //////////////
    vector <Osoba*> *lista;
    cin >> nr;
    if(nr==1)
        Wyswietl(dynamic_cast< vector <Pracownik*> >(lista)); // BLAD!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    return 0;
}
 

W jaki sposób mogę zmodyfikować kod, aby Dodawanie wybranego użytkownika do list jak i wyświetlanie tych list działało. Przyznam, że jeszcze nie mam doświadczenia z polimorfizmem aż tyle, aby poradzić sobie z tym problemem, dlatego zwracam się do was.
Dziękuję za poświęcony czas

PS Wiem, że kod wydaje sie troche bez sensu ale obrazuje problem w większym programie. Nie pracuje aktualnie na C++11

0

C++ nie posiada wektora polimorficznego - fakt, że jego typy są ze sobą powiązane nie sprawia, że możesz tak zrobić.
Użyj szablonów.

1
darthachill napisał(a):

Teraz chciałbym w zależności od sterowania wybrać liste do wyswietlenia. Tworze zatem:
+ vector <Osoba*> *lista; // wskaznikiem chce pokazywac na wybrana liste
+ funkcje Wyswietl
Przy probie wyświetlenia wyrzuca mi błąd

 Wyswietl(dynamic_cast< vector <Pracownik*> >(lista)); // BLAD!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

error: cannot dynamic_cast 'lista' (of type 'class std::vector<Osoba*>*') to type 'class std::vector<Pracownik*>' (target is not pointer or reference)|

W taki sposób nie możesz tego robić. Zależy, jak to wszystko wygląda i chcesz/możesz rozwiązać w tym większym programie, ale mógłbyś zrobić np. tak:

a) Modyfikacja funkcji Wyswietl:

template <typename T>
void Wyswietl(const std::vector<T*>& lista)
{
	for(typename std::vector<T*>::const_iterator it = lista.begin(); it != lista.end(); ++it)
	{
		(*it)->CzystoWirtualna();
	}
}
//...

Wyswietl(listaPracownikow);
Wyswietl(listaStudentow);

b) Bez konieczności modyfikowania funkcji Wyswietl:

template<class TargetType>
struct CastTo
{
    template<class Type>
    TargetType operator ()(Type& object) const
    {
		return static_cast<TargetType>(object);
    }

    template<class Type>
    TargetType operator ()(const Type& object) const
    {
		return static_cast<TargetType>(object);
    }
};
//...

void Wyswietl(const std::vector<Osoba*>& lista)
{
	for(std::vector<Osoba*>::const_iterator it = lista.begin(); it != lista.end(); ++it)
	{
		(*it)->CzystoWirtualna();
	}
}
//...

std::vector<Osoba*> listaOsob;

listaOsob.reserve(listaPracownikow.size());

std::transform(listaPracownikow.begin(), listaPracownikow.end(), std::back_inserter(listaOsob), CastTo<Osoba*>());

Wyswietl(listaOsob);

PS. proszę wszystkich o wybaczenie za mieszanie języków (wiem, fatalnie to wygląda), ale chciałem dopasować do zamieszczonego przez pytającego przykładu.

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