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


(Kabaneczek) #1

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;

}

(Xwars) #2

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:


(Fiołek) #3

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


(Sawyer47) #4

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ć.


(Kabaneczek) #5

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.


(Sawyer47) #6

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ę.