[C++] Kilka problemów z dziedziczeniem

0

*quetz: "poprzedni" watek: http:*4programmers.net/Forum/viewtopic.php?id=137312

Nikt mi nie odpisuje w starym temacie gdzie dołączyłem nowy program, więc zrobiłem osobny temat bo bardzo potrzebuję szybkiej pomocy w znalezieniu błędów, ewentualnie podpowiedzi, bo może jest jakiś lepszy sposób napisania tego. Poniżej to co udało mi się zrobić oraz treść zadania.

#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;

class RailVehicle
{
protected:
        int speed, mass;
        RailVehicle* RearVehicle;
        RailVehicle* FrontVehicle;
public:
        RailVehicle()
        {
                speed=0;
                mass=0;
                RearVehicle=NULL;
                FrontVehicle=NULL;
        }
        RailVehicle* ConnectToFrontVehicle(RailVehicle* FrontWsk)
        {       
                if (FrontWsk == NULL)
                {
                        this->FrontVehicle->RearVehicle=NULL;
                        this->FrontVehicle=NULL;
                }
                else if (this=&engine)
                {
                        cout<<"Lokomotywa moze byc tylko z przodu pociagu."<<endl;
                        return NULL;
                }
                else if ((this->FrontVehicle=NULL)&&(this->FrontVehicle->RearVehicle=NULL))
                {
                                this->FrontVehicle=FrontWsk;
                                this->FrontVehicle->RearVehicle=this;
                                return FrontWsk;
                }
                else
                {
                                cout<<"Nie mozna polaczyc tych wagonow."<<endl;
                                return NULL;
                }
        }
        virtual int GetSpeed() const
        {
                return speed;
        }
        int GetMassAll() const
        {
                int m;
                RailVehicle* wsk;
                wsk= &engine;
                do
                {
                        wsk->GetMassThis()=m;
                        mass += m;
                        wsk = wsk->RearVehicle;
                }
                while (this->RearVehicle!=NULL)
                return mass;
        }
        void ShowAll(ostream& o) const
        {
                o<<"Predkosc pociagu: "<<GetSpeed()<<endl;
                RailVehicle* wsk;
                wsk= &engine;
                do
                {
                        wsk->ShowThis(o);
                        wsk = wsk->RearVehicle;
                }
                while (this->RearVehicle!=NULL);
        }
        ~ RailVehicle()
        {
                this->RearVehicle->ConnectToFrontVehicle(NULL);
                this->ConnectToFrontVehicle(NULL);
        }
};

class Engine : public RailVehicle
{
private:
int engineMass;
public:
        Engine (int engineMass, int speed)
        {
                this->engineMass = engineMass;
                engineMass=0;
                this->speed = speed;
        }
        int ChangeSpeed(int value)
        {
                speed = value;
        }
        virtual int GetMassThis() const
        {
                return this->engineMass;
        }
        virtual void ShowThis(ostream& o) const
        {
                o<<"Lokomotywa o masie: "<<GetMassThis()<<endl;
        }
};

class FreightCar : public RailVehicle
{
private:
int freightCarMass;
public:
        FreightCar (int freightCarMass)
        {
                this->freightCarMass = freightCarMass;
                freightCarMass=0;
        }
        int AddFreight(int value)
        {
                if(speed=0)
                        this->freightCarMass += value;
                else
                        cout<<"Nie można wykonać załadunku w trakcie jazdy!"<<endl;
        }
        int RemoveFreight(int value)
        {
                if(speed=0)
                        this->freightCarMass -= value;
                else
                        cout<<"Nie można wykonać rozładunku w trakcie jazdy!"<<endl;
        }
        virtual int GetMassThis() const
        {
                return this->freightCarMass;
        }
        virtual void ShowThis(ostream& o) const
        {
                o << "Wagon towarowy o masie: "<<GetMassThis()<<endl;
        }
};

int main()
{
        cout<<"Stworzymy 3 obiekty: lokomotywe oraz 2 wagony towarowe, a nastepnie polaczymy je."<<endl;
        Engine lokomotywa(10,10);
        FreightCar wagon1(5);
        FreightCar wagon2(5);

        wagon1.ConnectToFrontVehicle(lokomotywa);
        wagon2.ConnectToFrontVehicle(wagon1);
       
        cout<<"Informacje o wagonie nr 1:"<<endl<<endl;
        wagon1.ShowThis(cout);
        system("Pause");
       
        cout<<endl<<"Informacje o calym pociagu"<<endl<<endl;
        ShowAll(cout);
        system("Pause");
       
        cout<<"Dokonamy zaladunku wagonu nr 2, a nastepnie zmienimy predkosc lokomotywy"<<endl<<endl;
        wagon2.AddFreight(20);
        lokomotywa.ChangeSpeed(100);
        cout<<endl<<"Informacje o calym pociagu"<<endl<<endl;
        ShowAll(cout);
        system("Pause");

        cout<<"Odlaczymy wagon nr 2 od pociagu."<<endl<<endl;
        wagon2.ConnectToFrontVehicle(NULL);
        cout<<endl<<"Informacje o calym pociagu"<<endl<<endl;
        ShowAll(cout);
       
        system("Pause");
        return 0;
}

Cel:
Symulacja pociągów, zabawa z łączeniem wagonów i lokomotyw, ładowaniem towarów do
wagonów i zmiana prędkości pociągów.

Na ocenę 3:
Opracować szkielet systemu w oparciu o poniższe klasy i funkcje.

RailVehicle -- abstrakcyjna klasa bazowa dla wszystkich pojazdów szynowych. Umożliwia
łączenie pojazdów. Umożliwia wyświetlanie stanu i zawartości pojazdów. Funkcje:
RailVehicle* ConnectToNext(RailVehicle* nextPtr)
virtual int GetSpeed() const;
virtual void ShowThis(ostream& o) const = 0;
void ShowAll(ostream& o) const;

Engine - lokomotywa. Umożliwia zmianę prędkości pociągu. Dziedziczy po RailVehicle. Ma
maksymalną prędkość. Funkcje:
int ChangeSpeed(int value)

FreightCar - wagon towarowy. Dziedziczy po RailVehicle.

Zasady łączenia pojazdów:
Pojazdy można połączyć jeśli z danej strony nie są do niczego podłączone. Do łączenia służy jedna
funkcja, podłączająca pojazd do następnego w szeregu. Aby połączyć pojazdy, należy podać
wskaźnik do następnego pojazdu. Aby rozłączyć pojazdy, należy podać NULL. W przypadku
pomyślnej operacji funkcja zwraca wskaźnik do dołączanego pojazdu, w przeciwnym wypadku
rzuca wyjątek. Zniszczenie pojazdu powoduje odłączenie go od sąsiadów. Lokomotywę można
dołączyć tylko na początku pociągu. Do lokomotywy nie można dołączyć innej lokomotywy.
Zasady zwracania prędkości pociągu:
Każdy pojazd można zapytać o prędkość pociągu. Używając wskaźników do poprzedniego pojazdu
dochodzi on do czoła pociągu i jeśli jest tam lokomotywa, zwraca jej prędkość
Inna funkcjonalność:
Funkcje ShowThis i ShowAll mają odpowiednio wyprowadzać do strumienia informację o
pojedynczym pojeździe i całym pociągu.
Zagadka:
Co będzie jeśli w destruktorze RailVehicle wywołana zostanie funkcja wirtualna, np.
GetSpeed w celu sprawdzenia czy pociąg stoi?

Na ocenę 4:
Umożliwić ładowanie i rozładowywanie towarów. Dodać do klasy FreightCar funkcje:
int AddFreight(int mass)
int RemoveFreight(int mass)

Zasady załadunku i rozładunku:
Można przeprowadzać tylko gdy pociąg stoi. Załadowanie powoduje dodanie masy ładunku do
masy danego wagonu. Zdjęcie ładunku odejmuje masę ładunku od masy wagonu.
Inna funkcjonalność:
Funkcje ShowThis i ShowAll mają zostać uzupełnione o wyprowadzanie do strumienia
odpowiednio informacji o masie ładunków w pojedynczym pojeździe i w całym pociągu.

Na ocenę 5:
Uwzględnić masę pociągu w wyznaczaniu jego prędkości. Uzupełnić klasę RailVehicle o
funkcje:
int GetMassAll() const;
virtual int GetMassThis() const = 0;

Zasady zwracania masy danego pojazdu:
Dla wagonu masa jest sumą stałej masy wagonu (przekazywanej w konstruktorze) i masy towarów.
Dla lokomotywy jest jej stałą masa (przekazywaną w konstruktorze).
Zasady zwracania masy pociągu:
Każdy pojazd można zapytać o masę całego pociągu. Używając wskaźników do poprzedniego i
następnego pojazdu sumuje on masy pojazdów i zwraca te sumę.
Zasady zmiany prędkości pociągu:
W konstruktorze lokomotywy przekazywane są jej maksymalna prędkość bez obciążenia.
Maksymalna prędkość pociągu jest ustalana na podstawie maksymalnej prędkości lokomotywy oraz
masy pociągu. Dla zerowej masy całkowitej pociągu prędkość maksymalna równa jest
maksymalnej prędkości lokomotywy, każda tona masy to spadek prędkości maksymalnej o 1km/h.
(uwaga: pociąg nigdy nie będzie jechał z maksymalną prędkością lokomotywy, bo sama
lokomotywa ma już pewną masę).

0

Jak zawsze wielkie dzięki adf88, a teraz kilka pytań zanim zacznę przerabiać swoje "wypociny" ;-P:

  1. Rozumiem, że int speed powinno być Twoim zdaniem publiczne, ale czemu skoro i tak każda klasa dziedzicząca i zaprzyjaźniona ma dostęp do zmiennych chronionych?

  2. Przecież używam "mass", chociażby w GetMassAll() i założyłem właśnie, że jest to masa pociągu bez ładunku, więc gdzie jest błąd?

  3. Przeładować metodę w engine tzn. tak samo jak w przypadku GetSpeed() ?? W ten sposób pozbędę się wszędzie "magicznej zmiennej engine" ;-P.

  4. Błędy typu "co jak FrontVehicle=NULL, RearVehicle=NULL" - jeśli dobrze myślę wystarczy dodać pętlę if tak? W przypadku odłączenia można zwrócić uwagę, że nie ma od czego odłączać, i zwrócić NULL, a w destruktorze po prostu ominąć odłączanie od RearVehicle bo go nie ma. Zgadza się?

  5. Jeśli dobrze myślę, to w GetMassAll() i ShowAll() muszę użyć warunku "while" i za jago pomocą dojść do momentu aż FrontVehicle=NULL a w drugą stronę RearVehicle=NULL, za każym razę dodając masę obiektu, na który aktualnie wskazuję do masy całego pociągu (mass).

  6. Dlaczego mam brać pod uwagę prędkość dopuszczalną? Przecież w zadaniu nikt nie zakazał mi stworzenia pociągu, który będzie poruszał się z dowolną prędkością? Na logikę owszem - każdy pojazd ma jakąś prędkość maksymalną ze względu na moc, ale w przypadku takiej "symulacji" obiekt nie musi być chyba aż tak realny? :> Przecież przy dodawaniu masy też mógłbym założyć, że zależy to jeszcze od objętości, kształtu, rozmiarów ładunku, itp.

  7. Masa samego wagonu to frightCarMass i jest od razu przypisana jej wartość 0, oczywiście mogę być tu bardziej realny i określić liczbą większą od zera, ale to chyba nie ma aż takiego znaczenia?

  8. Metody AddFreight() i RemoveFreight() nic nie zwracają... czyli muszę dodać do nich "return freightCarMass" tak?

  9. if(speed=0) - zły operator, hmmm no to chyba if(speed==0) będzie już dobrze? :-)

To chyba tyle, bo co do odejmowania masy to zrozumiałe - trzeba zaznaczyć, że nie można odjąć więcej niż (masa_wagonu_z_towarem - masa_samego_wagonu). Jeśli w czymś się mylę to proszę naprowadź mnie na dobrą drogę.

I jeszcze raz wielkie dzięki za wszystko :-).
Pozdrawiam!

0
  1. Prędkość ma być zapisana jedynie w lokomotywie

Każdy pojazd można zapytać o prędkość pociągu. Używając wskaźników do poprzedniego pojazdu dochodzi on do czoła pociągu i jeśli jest tam lokomotywa, zwraca jej prędkość
W komentarzu podałem przykład jak to można zrobić (prywatne pole "int speed" posiada tylko lokomotywa).

  1. Masa całego pociągu nie ma być zapisana nigdzie, masz ją obliczać za każdym razem

Każdy pojazd można zapytać o masę całego pociągu. Używając wskaźników do poprzedniego i następnego pojazdu sumuje on masy pojazdów i zwraca te sumę.

  1. Tak. Zwróć uwagę, że z przodu każdego pojazdu oprócz lokomotywy można dołożyć każdy inny pojazd. Natomiast z przodu lokomotywy nie można dołożyć żadnego pojazdu.

  2. Tak.

  3. Tak. Tylko sumę mas musisz jedynie zwrócić jako wynik funkcji, nigdzie zapisywać.

W konstruktorze lokomotywy przekazywane są jej maksymalna prędkość bez obciążenia.
Maksymalna prędkość pociągu jest ustalana na podstawie maksymalnej prędkości lokomotywy oraz
masy pociągu. Dla zerowej masy całkowitej pociągu prędkość maksymalna równa jest
maksymalnej prędkości lokomotywy, każda tona masy to spadek prędkości maksymalnej o 1km/h.
(uwaga: pociąg nigdy nie będzie jechał z maksymalną prędkością lokomotywy, bo sama
lokomotywa ma już pewną masę).

  1. Rozdziel masę wagonu na masę własną i masę ładunku.

Masa własna dotyczy zarówno lokomotywy jak i wagonu tak więc tą funkcjonalność zawrzyj w klasie RailVehicle. Dodaj prywatne pole "mass" oraz publiczną wirtualną metodę "GetMassThis()", która zwraca jego wartość. Niech "mass" będzie można określić w konstruktorze.

W wagonie towarowym przeładuj "GetMassThis()" dodając masę ładunku:

return 
   RailVehicle::GetMassThis() //masa własna
   + freightMass; //masa ładunku
  1. W deklaracji podałeś, że zwracają "int" a nie zwracasz nic. Zamień na "void".

  2. Tak.

0

Większość błędów, na które wskazał kompilator usunąłem. Jeden problem opisałem jako komentarz. jest jeszcze jeden, którego nie rozumiem, mianowicie:

In member function int RailVehicle::GetMassAll() const': 'const class RailVehicle' has no member named 'GetMassThis' In member function void RailVehicle::ShowAll(std::ostream&) const':
'const class RailVehicle' has no member named 'ShowThis'

Kod: http://pastebin.4programmers.net/37

0
#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;

class RailVehicle
{
private:
        int mass; //masa własna
protected:
        RailVehicle* RearVehicle;
        RailVehicle* FrontVehicle;
        
       
        //przyda się
        RailVehicle* FindFirstVehicle() const
        {
                const RailVehicle *wsk = this;
                while(wsk->FrontVehicle != NULL) 
                        wsk = wsk->FrontVehicle;
                return wsk;
        }
public:
        RailVehicle(int mass = 0) //mase własną przyjmuje konstruktor
        {
                this->mass = mass;
                RearVehicle=NULL;
                FrontVehicle=NULL;
        }

        //pobranie masy tyczy się każdego RailVehicle, ta metoda musi być w tej klasie
        virtual int GetMassThis() const 
        {
                return mass;
        }
        
        //ShowThis również tyczy się każdego RailVehicle, ta metoda będzie czysto-wirtualna
        virtual void ShowThis() const  = 0;
        
        //brakowało "virtual"
        virtual RailVehicle* ConnectToFrontVehicle(RailVehicle* FrontWsk)
        {       
                //TU SPRAWDZ JESZCZE, CZY POCIAG STOI

                if (FrontWsk == NULL)
                {
                        if (this->FrontVehicle==NULL)
                        {
                                cout<<"Przeciez wagon nie jest podlaczony."<<endl;
                                return 0;
                        }
                        else
                        {
                                this->FrontVehicle->RearVehicle=NULL;
                                this->FrontVehicle=NULL;
                                return this; //niech funkcja zawsze coś zwraca sensownego (wartosc != 0 przy powodzeniu)
                                //inaczej wartością zwróconą będzie śmieć z pamięci o bliżej nieokreślonej wartości
                        }
                }
                else if ((this->FrontVehicle==NULL)&&(FrontWsk->RearVehicle==NULL)) //poprawka warunku
                {
                        this->FrontVehicle=FrontWsk;
                        FrontWsk->RearVehicle=this;
                        return FrontWsk;
                }
                else
                {
                        cout<<"Nie mozna polaczyc tych wagonow."<<endl;
                        return NULL;
                }
        }
        virtual int GetSpeed() const
        {
        
                //const RailVehicle *wsk = this; - nie chodzi o this, this jest zwykle != null :)
                
                //sprawdzamy czy pojazd jest pierwszy w pociągu, jeśli tak to zwracamy 0 (brak lokomotywy)
                if(FrontVehicle == NULL) return 0;
                
                //zwracamy prędkość pierwszego pojazdu, szukanie możemy rozpocząć już od następnego pojazdu
                return FrontVehicle->FindFirstVehicle()->GetSpeed();
        }
        int GetMassAll() const
        {
                int m=0;
                const RailVehicle* wsk = this;
                //const RailVehicle* wsk2 = this->RearVehicle; //wystarczy jeden wsk
                
                //this przeważnie jest różny od NULL, a przynajmniej tak trzeba założyć 
                //jeśli this == NULL to mamy błąd w kodzie który trzeba poprawić
                //if(wsk1 == NULL)
                //{       
                //        cout<<"Nie ma takiego obiektu!"<<endl;
                //        return 0;
                //}
                do
                {
                        m += wsk->GetMassThis();
                        wsk = wsk->FrontVehicle;
                }
                while (wsk != NULL);
                
                wsk = this->RearVehicle;
                while(wsk != NULL)
                {
                        m += wsk->GetMassThis();
                        wsk = wsk->RearVehicle;
                }
                
                return m;
        }
        void ShowAll(ostream& o) const
        {
                //tu warto zacznąć od poczatku
                const RailVehicle* wsk = FindFirstVehicle();
                o<<"Predkosc pociagu: "<<wsk->GetSpeed()<<endl;
                do
                {
                        wsk->ShowThis(o);
                        wsk = wsk->RearVehicle;
                }
                while (wsk);
        }
        ~ RailVehicle()
        {
                //małe poprawki
                if(FrontVehicle) ConnectToFrontVehicle(NULL);
                if(RearVehicle) RearVehicle->ConnectToFrontVehicle(NULL);
        }
};

class Engine : public RailVehicle
{
protected:
        int maxspeed, speed;
public:
        Engine (int engineMass, int maxspeed)
           : RailVehicle(engineMass) //przekazujemy masę do konstruktora RailVehicle
        {
                this->maxspeed = maxspeed;
                this->speed=0;
        }
        //brakowało "virtual"
        virtual RailVehicle* ConnectToFrontVehicle(RailVehicle* FrontWsk)
        {
                cout<<"Lokomotywa moze byc tylko z przodu pociagu."<<endl;
                return NULL;
        }
        void ChangeSpeed(int value)
        {
                //to tutaj musisz uwzględnić masę pociągu
                int max = maxspeed - GetMassAll();
                if(value < max) value = max;
                speed = (value < 0) ? 0 : value;
        }
        virtual int GetSpeed() const
        {
                return speed;
        }

        virtual void ShowThis(ostream& o) const
        {
                o<<"Lokomotywa o masie: "<<GetMassThis()<<endl;
        }
};

class FreightCar : public RailVehicle
{
protected:
        int freightMass;
public:
        FreightCar (int freightCarMass)
           : RailVehicle(freightCarMass)  //przekazujemy masę do konstruktora RailVehicle
        {
                this->freightMass=0;
        }
        void AddFreight(int value)
        {
                if (this->GetSpeed()==0)
                        this->freightMass += value;
                else
                        cout<<"Nie można wykonać załadunku w trakcie jazdy!"<<endl;
        }
        void RemoveFreight(int value)
        {
                if (this->GetSpeed()==0)
                {
                        if (value<=freightMass)
                                this->freightMass -= value;
                        else
                                cout<<"Masa towaru znajdujacego sie na wagonie jest mniejsza od podanej przez Ciebie wartosci."<<endl;
                }
                else
                        cout<<"Nie można wykonać rozładunku w trakcie jazdy!"<<endl;
        }
        virtual int GetMassThis() const
        {
                //masę własną pobieramy przez RailVehicle
                return RailVechicle::GetMassThis() + freightMass;
        }
        virtual void ShowThis(ostream& o) const
        {
                o << "Wagon towarowy o masie: "<<GetMassThis()<<endl;
        }
};

No i miałeś jeszcze użyć wyjątków bodajże.

0

boze drogi, ludzie!!! uzywajcie pastebina! ja rozumiem wkleic kod 'startowy' czy tez 'koncowy' jak juz sie sadzi ze sie skonczylo, ale takietamtymczasowe.. jak sie obawiacie ze z pastebina cos wyparuje, to przeciez zawsze mozna ustawic zeby niewygasalo po 72h

0

Dzięki quetzalcoatl to teraz powiedz mi jak mam to odczytać? Bo chyba zniknęło :(

A jutro muszę oddać program.

//quetz: cudem znalazlem jeszcze ten kod. wyparowal z pastebina.. musialem zapomniec zmienic opcje wygasania z 72h na infinite.. eh. sorry.. grunt ze sie znalazl ^^"

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