Klasa główna,2 klasy pochodne i metoda wyświetl. dane[C++]

Nie jestem pewien czy dobrze to ująłem ;] Mam nadzieję że zrozumiecie…jeżeli pokażę calutki listning programu i kod sprawdzający w main do którego nie wiem jak się zabrać… bo jak nie próbuję to nic z tego nie wychodzi…

więc całe zadanie brzmi tak:

Utworzyc prosta hierarchie klas – klase bazowa osoba oraz klasy pochodne student

i słuchacz (wolny słuchacz). Klasa osoba powinna zawierac pola pozwalajace na

zapisywanie nazwiska osoby (u yc typu string*) oraz liczby lat. Klasa student powinna

posiadac dodatkowo pola kier - (kierunek studiów) oraz nr (numer indeksu), natomiast

słuchacz pola kier i sred ( srednia ocen na swiadectwie maturalnym).

We wszystkich klasach zdefiniowac metody pozwalajace na korzystanie z wartosci pól

składowych klasy. Ponadto zdefiniowac metode pokaz(), której u ycie pozwoli wyswietlac

wartosci wszystkich pól składowych klasy.

Mnie z kodu sprawdząjacego nie wychodzi ta linijka ponieważ nie potrafię zrobić metody w klasie pochodnej która będzie wyswietlać również dane publiczne z klasy nadrzędnej.

cout << tab[4]->numer1()<< endl;

Cały kod programu:

#include

#include



using namespace std;

class osoba

{

    public: 

      string *nazwisko;

      int wiek;


     osoba(string naz = "", int w = 0):nazwisko(new string(naz)),wiek(w){};

      osoba(const osoba &obiekt):nazwisko(new string(*obiekt.nazwisko)),wiek(obiekt.wiek){} 

      ~osoba(){delete nazwisko,wiek;};

       ostream& pokaz (ostream & )const;

      osoba &operator=(const osoba &obiekt); 

      string nazwisko1(){return (*nazwisko);}

      int wiek1(){return (wiek);}

};


ostream& osoba::pokaz (ostream & out)const 

{

  return out <<"Nazwisko: "<< nazwisko <<" Wiek : "<
}


      ostream& operator<<(ostream &out,const osoba& obiekt ) 

      {

              return out <<"Nazwisko: "<< *obiekt.nazwisko <<" Wiek : "<
              }


class student : public osoba

{


      string *kier;

      int nr;

      public:

      student(string naz="",int w=0,string k="",int n=0):osoba(naz,w),kier(new string(k)),nr(n){}

      student (const student & obiekt):osoba(obiekt){kier = obiekt.kier; nr=obiekt.nr; }


      ~student(){}

      ostream& pokaz (ostream &);


      student &operator=(const student &obiekt);


      friend ostream& operator<<(ostream & ekran, const student & obj);


       int numer1(){return (nr);}


      };


class sluchacz : public osoba 

{public:

      string *kier;

      double sr;


      sluchacz(string naz="",int w=0,string k="", double s=0):osoba(naz,w),kier(new string(k)),sr(s){}

      sluchacz(const sluchacz &obiekt):osoba(obiekt){kier=obiekt.kier, sr=obiekt.sr;}

      sluchacz &operator=(const sluchacz &obiekt);

      ~sluchacz(){}

      friend ostream& operator<<(ostream & ekran, const sluchacz & obj);


      };


/ ******************************************************************************** /

osoba&osoba::operator=(const osoba &obiekt) 

{ if (this==&obiekt) return *this;


  *nazwisko=*obiekt.nazwisko;

  wiek=obiekt.wiek;

  return *this;

}

student & student::operator=(const student &obiekt){

                                 (*this).osoba::operator=(obiekt);

                                 kier=obiekt.kier;

                                 nr=obiekt.nr;


                                 }


sluchacz & sluchacz::operator=(const sluchacz &obiekt){

                                     (*this).osoba::operator=(obiekt);

                                     kier=obiekt.kier;

                                     sr=obiekt.sr;

                                     }

/ ******************************************************************************** /

/ ******************************************************************************** /

/ ******************************************************************************** /

ostream & operator <<(ostream &ekran, const student &obj)

{

        ekran << obj.nazwisko 

              << obj.wiek

              << obj.kier

              << obj.nr<
              return ekran;

              }

ostream& student::pokaz (ostream &out)

      {

              return out <<"kierunek : "<< *kier<
              }


int main(){


osoba *tab[10]; 



osoba o1("Dolas", 21);

student o2("Dyzama", 22, "ekonomia", 15678);

sluchacz o3("Kania", 22, "budownictwo", 3.75);

osoba o4("Kos", 19);

student o5("Jelen", 18, "informatyka", 15700);


cout<< o3.nazwisko1()<<" " << o3.wiek1()<<" " << endl;

cout << o5.nazwisko1()<<" " << o5.numer1()<<" " << endl;


tab[0] = &o1;

tab[1] = &o2;

tab[2] = &o3;

tab[3] = new osoba;

tab[4] = new student;

 cout<< tab[0]->nazwisko1() << endl;

//cout << tab[4]->numer1()<< endl;// TEGO NIE POTRAFIĘ ZROBIĆ 


*tab[3] = o4;

*tab[4] = o5;


for (int i=0; i<5; ++i)

cout<< *tab[i] <
    system ("pause");

   return 0;

}

Z punktu widzenia kompilatora chcesz wywołać metodę numer1() na obiekcie klasy obiekt, który jej nie implementuje. O ile wiem żaden język który dba o typy na to nie pozwoli, wiec musiałbyś zrobić coś w stylu

cout << (student)tab[4]->numer1()<< endl;

Kolejny problem, ale już specyficzny dla C++, jest przy wypisywaniu zmiennych. Używane są funkcje zdefiniowane dla ‘osoba’ mimo że faktycznie są to obiekty np. klasy ‘student’. Tu też będziesz musiał rzutować, choć np. w Javie przeszło by to bez problemu.

P.S. Niej jestem guru i mogłem tu jakieś głupoty napisać :slight_smile:

Dobrze powiedział ucho3000 z tym, że musisz rzutować na wskaźnik na studenta, nie na studenta.

No parę uwag jest.

linijki 1,2: spacja między include a nazwą biblioteki polepsza czytelność

linijka 13: destruktor - {delete nazwisko,wiek;} nie zadziała. W C++ istnieje operator , (przecinek), którego wynikiem jest wartość najbardziej po prawej (oczywiście o ile nie jest przeładowany). Jeżeli kompilator nie rzuci ostrzeżeniem to prawdopodobnie potraktuje to jako delete wiek (a pola wiek nie można usunąć delete bo nie było rezerwowane w pamięci operatorem new). Możliwe, że pole wiek przez przypadek tam wpisałeś. Ciało destruktora powinno wyglądać po prostu { delete nazwisko; }

No i to o co Ci chodzi. Nie musisz rzutować, raczej się tego unika. Słowo kluczowe to virtual. Jeżeli zdefiniujesz metodę w klsaie bazowej jako wirtualną to będzie ona dostępna w klasie pochodnej. Czyli deklaracje metod, które chcesz wywoływać na klasie pochodnej poprzedź słowem virtual. Po tym zabiegu powinno działać.

Jeżeli wstawiam słowo virtual przy metodzie to kompilator woła że nie może utworzyć obiektów klasy osoba ponieważ w klasie jest virtualna funkcja przez to klasa staje się abstrakcyjna. Więc tak by się dało zrobić ale nie w momencie jeżeli tworzone są obiekty klasy głównej. Czy dobrze mówie? Nadal nie wiem jak zmienić kod żeby to zadziałało tak jak powinno. Dzięki za odpowiedzi.

Ups sorry. Pomyliłem się lekko i na odwrót napisałem :slight_smile: Owszem, jeżeli chcesz wywołać metodę klasy nadrzędnej na wskaźniku/referencji klasy pochodnej to wtedy deklarujesz ją jako wirtualną. Natomiast faktycznie jeżeli chcesz wywołać metodę z klasy pochodnej na wskaźniku klasy podstawowej to trzeba go zrzutować na wskaźnik do klasy pochodnej. Można do tego użyć operatora dynamic_cast:

student* studentZOsoby = dynamic_cast(tab[4]);

	if(studentZOsoby)

		cout << "DC: " << studentZOsoby->numer1()<< endl;

Sorry za pomyłkę.