Polimorfizm + listy dynamiczne.

Odpowiedz Nowy wątek
2015-05-30 18:21
0

Witam.
Mniej więcej orientuję się na czym polega polimorfizm, oraz jak go zastosować w przypadku gdy tworzymy nowy obiekt w mainie za pomocą jakiegoś konstruktora, a następnie chcemy go np. wyświetlić. Ale nie ważne co, wiem. Nie wiem jak zastosować polimorfizm w przypadku gdy:

  1. Mam 3 klasy: Osoba - klasa bazowa; Student - klasa dziedzicząca; Pracownik - klasa dziedzicząca.

  2. Wczytuję studentów i pracowników z pliku oddzielną funkcją i dodaję ich do jednokierunkowej listy dynam. również 2 funkcjami typu:


void dodajp(pracownik* (&glowa), pracownik* dodaj) {

    //jeśli głowa nie istnieje
        if(glowa == NULL){
                glowa = dodaj;
                glowa->nast = NULL;
        }
        //jeśli głowa istnieje
        else{
                pracownik *wsk = NULL;
                for(wsk = glowa; wsk->nast != NULL; wsk = wsk->nast){ }
                wsk->nast = dodaj;
                wsk->nast->nast = NULL;

        }

}

Rzecz w tym, że chcę to wszystko robić jedną funkcją z wykorzystanie polimorfizmu. Jeszcze dla wyjaśnienia dodam, że drugi argument który przyjmuje funkcja dodajp, to obiekt utworzony przez funkcję dodawania nowego pracownika. Analogicznie dla studenta.

W mainie dodaję tylko student glowa; pracownik glowa. Ktoś mi powie, czy muszę zmienić wszystkie funkcje włączając w to dodawanie do listy, czy da się jakoś zrobić np. tylko wyświetlanie z wykorzystaniem polimorfizmu?


void pokazs(student* glowa){

        fun("Wyświetlanie listy studentów"); 
        student* a;

        cout << "\t\t** STUDENCI ** \n\n";
        cout << "Nr ID\t\tNazwisko\tOcena\n\n";

        for(a = glowa; a != NULL; a = a->nast){
                a->wypisz();
        }

        cout << endl;

}
edytowany 1x, ostatnio: adamtt, 2015-05-30 18:23

Pozostało 580 znaków

2015-05-30 19:15
0

W takim razie to musi być jedna wspólna lista osób, zamiast listy pracowników i listy studentów.

void dodajp(Osoba*& glowa, Osoba* nowa)

W najlepiej to lista powinna być klasą, a dodaj jej metodą.

Pozostało 580 znaków

2015-05-30 19:18
0

ehh, tak też myślałem. Dobra, przerobię dodawanie i będę pytał dalej

Pozostało 580 znaków

2015-05-30 19:26
0

Dobra, to załóżmy, że mam coś takiego:


class lista{
protected:
    pracownik *glowa_pracownik;
    student *glowa_student;

public:
    lista():
      glowa_student(NULL), glowa_pracownik(NULL) {}

      void dodaj(student *dodaj_s){
          if(glowa_student == NULL){
              glowa_student = dodaj_s;
              glowa_student->nast = NULL;
          }else{
              student *wsk;

              for(wsk=glowa_student; wsk->nast!= NULL; wsk = wsk->nast);
              wsk->nast = dodaj_s;
              wsk->nast->nast = NULL;
          }
      }
          void dodaj(pracownik *dodaj_p){
              if(glowa_pracownik == NULL){
                  glowa_pracownik = dodaj_p;
                  glowa_pracownik->nast = NULL;
              }else{
                  pracownik *wsk;

                  for(wsk = glowa_pracownik; wsk->nast!=NULL; wsk=wsk->nast);
                  wsk->nast = dodaj_p;
                  wsk->nast->nast = NULL;
              }
          }

          void wypisz(){
              student *a;
              pracownik *b;

              cout << "      ** LISTA STUDENTOW **" << endl;
              for(a=glowa_student; a!=NULL; a=a->nast){
                  a->wypisz();
                  cout << endl << endl;
              }

              cout << "     ** LISTA PRACOWNIKOW **" << endl;
              for(b=glowa_pracownik; b!=NULL; b=b->nast){
                  b->wypisz();
                  cout << endl << endl;
          }
          }

Pozostało 580 znaków

2015-05-30 19:28
0

Przejrzyj sobie kod parsera: http://kaczus.republika.pl/izv/parser.lha Był on dodawany do prehistorycznego kompilatora MaxonC, ale bardzo fajnie tam zastosowany polimorfizm. W dawnych czasach rozpoznawałem ten przykład i kila rzeczy opisałem w magazynie Izviestia. Artykuł jest przedpotopowy, ale może pomoż tez coś zrozumieć (albo bardziej zagmatwa) http://kaczus.republika.pl/izv/parser.html


Ogólnie na prace domowe mam stawki zaporowe. Czasem coś o programowaniu znajdzie się na mojej stronie

Pozostało 580 znaków

2015-05-30 20:08
0

Nie, jedna lista, nie dwie listy opakowane w jedną klasę.

class List
{
public:
    void add(Person* newPerson);
    void show();
protected:
    Person* head = nullptr;
};
edytowany 1x, ostatnio: twonek, 2015-05-30 20:08

Pozostało 580 znaków

2015-05-30 20:21
0
class lista{
protected:
    osoba *glowa;

public:
    lista(){
        glowa = NULL;

    }

    void dodaj(osoba *dodaj){
          if(glowa == NULL){
              glowa = dodaj;
              glowa->nast = NULL;
          }else{
              osoba *wsk;

              for(wsk=glowa; wsk->nast!= NULL; wsk = wsk->nast);
              wsk->nast = dodaj;
              wsk->nast->nast = NULL;
          }
    }

};

No dobra, mam taką klasę. Ale mam tam

void dodaj(osoba*dodaj)

a na przykład chcę dodać studenta. A przecież student != osoba.

  1. Po pierwsze, u mnie funkcja dodawania nowego studenta wygląda tak:

student dodaj_s(student glowa){
fun("Dodawanie studenta: ");
int a;
string naz;
student *wsk = glowa;

    cout << "Podaj nr ID studenta: ";
    while((scanf_s("%d", &a))!=1 || a<=9999 || a>=100000 || getchar()!='\n'){
            cout << "Nr ID musi skladac sie z 5 cyfr!\n" ;
            cout << "Wprowadz ponownie:\n" ;
            while(getchar()!='\n');
    }
    while(wsk!=NULL){
            int ID = wsk->getID();
            if(ID == a){
                    cout << "Student z takim ID juz figuruje w bazie\n";
                    while((scanf_s("%d", &a))!=1 || a<=9999 || a>=100000 || getchar()!='\n'){
                            cout << "Nr ID musi skladac sie z 5 cyfr!\n" ;
                            cout << "Wprowadz ponownie:\n" ;
                            while(getchar()!='\n');

                            }
                    wsk = glowa;
            }
    wsk = wsk->nast;
    }
    cout << "\nPodaj nazwisko studenta: ";
    cin >> naz;

    return new student(a,naz,-1);

}



chyba nie można dodać funkcji wirtualnej innej niż void, więc nie zwrócę w returnie nowego studenta
edytowany 1x, ostatnio: adamtt, 2015-05-30 20:22

Pozostało 580 znaków

2015-05-30 20:36
0
adamtt napisał(a):

A przecież student != osoba.
Oczywiście, że student jest osobą. Na tym polega dziedziczenie!

chyba nie można dodać funkcji wirtualnej innej niż void, więc nie zwrócę w returnie nowego studenta
Funkcja wirtualna może zwracać cokolwiek. Co więcej, wersja w klasie pochodnej może zwracać coś innego niż wersja w klasie bazowej, np.


struct Osoba
{
virtual Osoba* foo() = 0;
};

struct Student : public Osoba
{
virtual Student* foo() override;
}

Pozostało 580 znaków

2015-05-30 21:15
0

Teraz mam problem m.in. z tym, że nie mogę zwrócić

new student(x,y,z) 

ponieważ chyba uznaje mi klasę student jako abstrakcyjną.


#include<string>
#include <time.h>
#include<iostream>
#include<fstream>

#define N 20

using namespace std;

class osoba{
protected:
        float ocena;
        string nazwisko;
public:
    osoba *nast;
                osoba(float ocena1, string nazwisko1):    ////konstruktor dodaj
                ocena(ocena1), nazwisko(nazwisko1) {}

                virtual void wypisz()=0;   //metoda wirtualna - wypisz
                virtual void dodaj()=0;
                ///setery

                void setOcena (float ocena1){ ocena = ocena1;}
                void setNazwisko (string Nazwisko) {nazwisko = Nazwisko;}

                //getery

                float getOcena (){ return ocena;}
                string getNazwisko () {return nazwisko ;}
};

class student:public osoba{
protected:
        int ID;

public:

        student *nast;

        student(int ID1, string nazwisko1,float ocena1):
        ID(ID1), osoba(ocena1, nazwisko1) {}

        void wypisz(){
                cout << ID<< "\t\t";
                cout << nazwisko<< "\t\t";

                if(ocena!=-1){
                        printf("%.1f\t\t\n\n", ocena);
                }else{
                        cout << "\n\n";
                }
        }

        ///setery

        void setID (int id) {id = ID;}

        //getery

        int getID (){return ID;}

        ~student(){
        delete nast;
}

        void *nowy(){

        int a;
        string naz;

        cout << "Podaj nr ID studenta: ";
        while((scanf_s("%d", &a))!=1 || a<=9999 || a>=100000 || getchar()!='\n'){
                cout << "Nr ID musi skladac sie z 5 cyfr!\n" ;
                cout << "Wprowadz ponownie:\n" ;
                while(getchar()!='\n');
        }

                int ID;

        cout << "\nPodaj nazwisko studenta: ";
        cin >> naz;

        return new student(a,naz,-1);

        }
};

class pracownik:public osoba{
protected:
        int nr_umowy;

public:
        pracownik *nast;

        pracownik(int nrumowy, string nazwisko1, float ocena1):osoba(ocena1, nazwisko1)
        {
                nr_umowy = nrumowy;
                nazwisko = nazwisko1;
        }

        void wypisz(){
                cout << nr_umowy<< "\t\t";
                cout << nazwisko<< "\t\t";

                if(ocena !=-1){
                        printf("%.1f\t\t\n\n", ocena);
                }else {
                        printf("\n\n");
                }
                }

        ///setery

        void setNR(int NR) {nr_umowy = NR;}

        ///getery

        int getNR() {return nr_umowy;}

~pracownik(){
        delete nast;
}
};

ofstream wej("raport.txt");
void fun(string aa){
    time_t czas;
    string bum = aa;
    struct tm * ptr;
    time(&czas);
    ptr = localtime(&czas);
    char * data = asctime(ptr);
    //std::cout << "Data: " << data;
    ofstream plikout("raport.txt", ios::app);
    wej << bum << "         Data:  "<<data << endl;

}

class lista{

public:
    osoba *glowa;

    lista():
    glowa(NULL) {}

    void dodaj(osoba *dodaj){
        if(glowa == NULL){
            glowa = dodaj;
            glowa->nast = NULL;
        }else{
            osoba *wsk;
            for(wsk = glowa;wsk->nast !=NULL; wsk = wsk->nast);
            wsk->nast = dodaj;
            wsk->nast->nast = NULL;
        }

    }

    void wypisz(){
        osoba *a;
        osoba *b;

            for(a =this->glowa;a!=NULL;a=a->nast)
                a->wypisz();
            cout << endl;

            for(b =this->glowa;b!=NULL;b=b->nast)
                b->wypisz();
            cout << endl;

    }
};

int main(){

    lista *nowa = new lista();

    int wybor; 
    while(wybor == 0){
        cout << "1) student = 1\n2)pracownik = 2\n3)wyjscie = 0\n\n";
        cin >> wybor;

        student a();
        osoba *wsk;

        if(wybor == 1){

        }

    }

    return 0;
}
przepuść kod przez formater: http://format.krzaq.cc - twonek 2015-05-30 21:19

Pozostało 580 znaków

2015-05-30 21:24
0

Dlaczego student ma student* nast? Student nic nie wie o tym, że jest na jakiejś liście, to nie jego problem.

 void *nowy()

nie void*, tylko student*.

I ta cała metoda nowy(), która zwraca wskaźnik do nowego obiektu też nie wygląda najlepiej, ale to już inny problem.

Pozostało 580 znaków

2015-05-30 21:41
0

student *nast
zostało jeszcze z czasu, kiedy robiłem 2 listy.

No to jeśli ma być student *(), to jak mam do tego zrobić funkcję wirtualną w klasie Osoba?

I jeszcze: Jak mam się odwołać za pomocą

osoba *wsk
do funkcji z klasy student - getID - która zwraca mi wartość pola ID?

No i kurcze, dlaczego kiedy dodam w klasie osoba <quote> virtual void dodaj()=0; </qoute> to klasa student staje się abstrakcyjną i nie mogę zwrócić w tej funkcji która zasłania virtualną new student... ?

edytowany 2x, ostatnio: adamtt, 2015-05-30 21:57

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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