Problemy z dziedziczeniem i polimorfizmem w tablicach

0

Na początku przepraszam, jeśli namieszam. Napiłem się kawy, ale nadal nie ogarniam tego, mianowicie:

Mam klasę podstawową, nazwijmy ją "A". Mam stworzyć tablicę typu A, jednak obiekty, w zależności od potrzeb użytkownika, mam tworzyć z klas dziedziczących. Czyli powiedzmy, że po A dziedziczy:

  • AA
  • AB
  • AC

Jak użytkownik wybierze C to tworzę obiekt typu C na pozycji [x] w tablicy typu A. I to nie działa.

Dwa pytania:

  • czy to MOŻE działać?
  • czy TAK jest dobrze:
A tablica[size];
tablica[0] = AB();

To nie działa, krzyczy coś w stylu:

'A' is an inaccessible base of 'AB'

Co robię źle, tylko nie krzyczcie.

0

Wpisałem w google is an inaccessible base of 'AB'
i wynik: http://bytes.com/topic/c/answers/438984-b-inaccessible-base-d

I faktycznie, utworzyłem u siebie przykładowy kod

class A
{};

class AA : A
{};

class AB : A
{};

int main()
{
  A tab[3];
  
  tab[0] = AA();
}

Przy próbie kompilacji, wywaliło dokładnie taki sam błąd jak piszesz.
Poprawiłem, dopisując modyfikator public przy definiowaniu klasy AA:

class AA : public A

I poszło z górki.

0

Dziękować pięknie. Mam jeszcze jeden, być może banalny problem, ale dawno w C++ nie tworzyłem, a pora juz późna. Mianowicie:

Mam klasę a w niej pole typu INT. Wprowadzam do niego jakąś wartość, dajmy na to 150 a wychodzi mi dajmy na to 46xxxx. WHY? :(

0

najlepiej pokaz kod jak mozesz, są pewne podejrzenia, ale tak cięzko:)

0
           tablica[n] = Pracownik();
           
           cout << "Podaj pensje: " << endl;
           cin >> buffer;

           tablica[n].ustalPensje(buffer);
           cout << "Ustalona pensja to: " << (int)tablica[n].podajPensje();
0

Ale wy chyba kombinujecie za bardzo. Przecież samo wywołanie:

A tablica[10];

Spowoduje wywołanie konstruktora domyślnego u utworzenie tych obiektów. Nie wywołuje się potem zadnego
tablica[x] = A();
bo nie ma takiej potrzeby.
@autor: napisz konkretnie w czym problem i pokaż kawałek kodu KLASY, bo z tego co pokazałeś nic nie wynika.

0

No to generalnie tak, główny program wygląda tak, może bajzel, ale jest to wersja robocza, na początek chciałbym, żeby działało:

#include <cstdlib>
#include <iostream>
#include "osoba.h"
#include "pracownik.h"
#include "student.h"
#include "emeryt.h"
#include "rektor.h"

using namespace std;

void poprosDane()
{
 cout << "Podaj dane osoby w formacie: imie nazwisko rok_studiow :" << endl;   
}

int main(int argc, char *argv[])
{
    int rok;
    string imie, nazwisko;
    
    int buffer;
    int type;
    int size;
    int n = 0;
    string czy;
    bool next = true;
    cout << "Podaj ilosc wpisywanych osob:";
    cin >> size;
    
    Osoba tablica[size];
    
    //Petla wczytujaca osoby
    while(next)
    {
     next = false;
     
     cout << "Podaj kategorie:" 
     << endl << "(1) pracownik" 
     << endl << "(2) student"
     << endl << "(3) emeryt"
     << endl << "(4) rektor"
     << endl;
     
     cin >> type;
     
     switch(type)
     {
      case 1:
           
           poprosDane();
           cin >> imie >> nazwisko >> rok;
           tablica[n] = Pracownik(imie, nazwisko, rok);
           
           cout << "Podaj pensje: " << endl;
           cin >> buffer;

           tablica[n].ustalPensje(buffer);
           cout << "Ustalona pensja to: " << (int)tablica[n].podajPensje() << endl;
           cout << "Calkowity dochod po obliczeniu premii, wynosi: " << tablica[n].dochod() << endl;
           break;
      
      case 2:
           tablica[n] = Student();
           
           cout << "Poda wysokosc stypendium: " << endl;
           cin >> buffer;
           
           tablica[n].ustalStypendium(buffer);
           cout << "Ustalona wysokosc stypendium to: " << tablica[n].podajStypendium() << endl;
           cout << "Po odliczeniu podatku, dochod studenta wynosic bedzie: " << tablica[n].dochod() << endl;
           
           break;
      
      case 3:
           
           break;
           
      case 4:
           
           break;                
     }
     
     cout << "Wprowadzasz dalej? [t] / [n]:" << endl;
     cin >> czy;
     
     if (czy != "t") { next = false; }
     n = n + 1;
    }
    
    system("PAUSE");
    return EXIT_SUCCESS;
}

A nie działa.

Klasa osoba wygląda tak:

#include <string.h>

class Osoba
{
 public:

  void ustalImie(char* i) { strcpy(imie,i); }
  void ustalNazwisko(char* n) { strcpy(nazwisko,n); }
  void ustalRokUr(int r) { rokur=r; }

  const char* podajImie() { return imie; }
  const char* podajNazwisko() { return nazwisko; }
  int podajRokUr() { return rokur; }

  void ustalDane(char* i, char* n, int r)
  {
   ustalImie(i);
   ustalNazwisko(n);
   ustalRokUr(r);
  }

  Osoba(char* i, char* n, int r)
  {
   ustalDane(i,n,r);
  }

  //virtual methods
  virtual double dochod(){}
  virtual void ustalPensje( int pensja ){}
  virtual int podajPensje(){}
  virtual void ustalStypendium(){}
  virtual int podajStypendium(){}

  Osoba() {};

 private:
  char imie[40];
  char nazwisko[40];
  int rokur;
  
};

A np. klasa Pracownik wyglada tak:

class Pracownik : public Osoba
{
     private:
              int pensja;
              
     public:
              Pracownik(char* i, char* n, int r)
              {
               Osoba :: Osoba(i, n, r);         
              }
            
              void ustalPensje( int pensja )
              { this -> pensja = pensja; }
              
              int podajPensje()
              { return this -> pensja; }
              
              double podajPremie()
              { return 0,2 * this -> pensja; }
              
              double dochod()
              { return (this -> pensja + this -> podajPremie()) - (this -> pensja + this -> podajPremie() * 0,19); }
};

Patent jest taki, że MUSZĘ, taki mam prikaz, zrobić zunifikowaną tablicę, zawierającą różne typy, mam wyjść z klasy Osoba, jednak każda klasa dziedzicząca po osobie jest i tak obcinana. Kompilator nie widzi w Podklasie konstruktora, który wywołuje, albo metod które znajdują sie tylko i wyłącznie w danej podklasie. Czy to co chcę zrobić jest niewykonalne czy źle się do tego zabieram?

0
Pracownik(char* i, char* n, int r):Osoba(i, n, r) {}

To po pierwsze. Po drugie ZROZUM że aby działał polimorfizm musisz mieć wskaźniki albo referencje. A ty tworzysz tablicę obiektów typu Osoba! Rozwiązanie?

Osoba* tablica[10];
tablica[0] = new Pracownik(a,b,c);
tablica[1] = new Osoba(a,b,c); 
//itd a potem to oczywiście zwalaniasz! destruktory oczywiście też powinny być wirtualne
0

Robię jak każesz i dostaję, po pierwsze:

52 E:\Benny\studia\oop\2\main.cpp no matching function for call to `Pracownik::Pracownik(std::string&, std::string&, int&)'

A wszystkie wychodzące po za klasę Osoba metody, np. Stypendium() dla Studenta traktowane są jak "not-declared". Co mogłem spieprzyć? Bo na sto procent to mój błąd.

0

Z tego co widzę to wczytujesz dane do zmiennych typu string, a w konstruktorze masz char* To NIE jest to samo. Zamień w tych metodach i klasie char* na string.

0

Gdy wszystko zamieniam na string, co również próbowalem, dostaję komunikat, że zadeklarowane metody

  void ustalImie(char* i) { strcpy(imie,i); }
  void ustalNazwisko(char* n) { strcpy(nazwisko,n); }
  void ustalRokUr(int r) { rokur=r; }

są puste. Tzn.:

variable or field `ustalImie' declared void

:/

0

Z wcześniejszym problemem sobie poradziłem, chciałem jednak zapytać o coś znacznie prostszego jak mniemam. Na początek kod:

#include <cstdlib>
#include <iostream>
#include "osoba.h"
#include "pracownik.h"
#include "student.h"
#include "emeryt.h"
#include "rektor.h"

using namespace std;

void poprosDane()
{
 cout << "Podaj dane osoby w formacie: imie nazwisko rok_studiow plec[m/k] :" << endl;   
}

int main(int argc, char *argv[])
{
    double sumaDochod;
    
    int i;
    int rok;
    
    char imie[40];
    char nazwisko[40];
    char plec;
    
    int buffer;
    int type;
    int size;
    int n = 0;
    
    char czy;
    bool next = true;
    
    cout << "Podaj ilosc wpisywanych osob:";
    cin >> size;
    
    Osoba* tablica[size];
    
    //Petla wczytujaca osoby
    for(i = 0; i < size; i++)
    {
     cout << "Podaj kategorie:" 
     << endl << "(1) pracownik" 
     << endl << "(2) student"
     << endl << "(3) rektor"
     << endl << "(4) emeryt"
     << endl;
     
     cin >> type;
     
     switch(type)
     {
      case 1:  
           {   
               poprosDane();
               cin >> imie >> nazwisko >> rok >> plec;
               Pracownik *tmp = new Pracownik;
           
               cout << "Podaj pensje: " << endl;
               cin >> buffer;
               
               tmp -> ustalPensje(buffer);

               //debug
               cout << tmp -> dochod();

               tmp -> ustalDane(imie, nazwisko, rok, plec);
           
               tablica[n] = tmp;
               
               //debug
               cout << tablica[n] -> dochod();
               break;
           }
      case 2:
           {
               poprosDane();
               cin >> imie >> nazwisko >> rok;
               Student *tmp = new Student;
           
               cout << "Podaj wysokosc stypendium: " << endl;
               cin >> buffer;
           
               tmp -> ustalStypendium(buffer);
               tmp -> ustalDane(imie, nazwisko, rok, plec);
           
               tablica[n] = tmp;
               break;
           }
      case 3:
           {
               poprosDane();
               cin >> imie >> nazwisko >> rok;
               Rektor *tmp = new Rektor;
           
               cout << "Podaj wysokosc pensji: " << endl;
               cin >> buffer;
               tmp -> ustalPensje(buffer);
               
               cout << "Podaj wysokosc premii: " << endl;
               cin >> buffer;
               tmp -> ustalPremie(buffer);
               
               cout << "Podaj wysokosc dodatku: " << endl;
               cin >> buffer;
               tmp -> ustalDodatek(buffer);
               

               tmp -> ustalDane(imie, nazwisko, rok, plec);
           
               tablica[n] = tmp;
               break;
           }
           break;
           
      case 4:
           {
               poprosDane();
               cin >> imie >> nazwisko >> rok;
               Emeryt *tmp = new Emeryt;
                          
               cout << "Podaj wysokosc emerytury: " << endl;
               cin >> buffer;
           
               tmp -> ustalEmeryture(buffer);
               tmp -> ustalDane(imie, nazwisko, rok, plec);
           
               tablica[n] = tmp;
               break;   
           }
           break;    
           
      default:
           break;            
     };
    }
    
    for( i = 0; i < n; i++)
    {
     sumaDochod = sumaDochod + tablica[n] -> dochod();          
    }
    
    cout << "Calkowita suma wydatkow wynosi " << (int)sumaDochod << " zl." << endl;
    
    system("PAUSE");
    return EXIT_SUCCESS;
}

class Pracownik : public Osoba
{
     private:
              int pensja;
              
     public:
              void ustalPensje( int pensja )
              { this -> pensja = pensja; }
              
              int podajPensje()
              { return this -> pensja; }
              
              double podajPremie()
              { return 0,2 * this -> pensja; }
              
              double dochod()
              { return (this -> pensja + this -> podajPremie()) - (this -> pensja + this -> podajPremie() * 0,19); }
};

W pierwszy listingu mam miejsca zaznaczone jako debug. W tym miejscu sprawdzałem jaką wartość poda mi metoda dochod() bo pod koniec programu zawsze wychodziło 0. I scenariusz jest taki:

  1. Uruchamiam program
  2. Wybieram jedną osobę
  3. Wybieram pracownika
  4. Wpisuję dane
  5. Wpisuję pensję (2000)
  6. Proszę o podanie dochodu i wyskakuje mi w obu miejscach 5981. Czemu?
0
  1. Nigdzie nie widzę n++ po dodaniu osoby.
sumaDochod = sumaDochod + tablica[n] -> dochod();

? A nie chodziło czasem o

sumaDochod = sumaDochod + tablica[i] -> dochod(); // tablica[i] ;)

?

0

No właśnie nie, poprawiłem kilka literówek i generalnie cały czas otrzymuję:

a) w miejscu gdzie jest debug, zamiast np. 2000 dostaję 5981
b) pod koniec programu łączny dochód wynosi 0...

0

To weź z łaski swojej przetestuj to osobno. Nie jakimś gigantycznym kodem, tylko prosto, twórz osobne obiekty tych klas i wywołuj metody, potem testuj polimorfizm itd.

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