Przeładowanie operatora<< wypisującego, a dziedziczenie klas.

0

Cześć!
Piszę program, który ma klasę Samochód i Rower. Obie te klasy dziedziczą z klasy Pojazd. Chce wyświetlić składowe danej klasy. Chciałem przeładować operator<<. Mam jednak z tym spory problem, po przeszukaniu zagranicznych stron udało mi się napisać coś takiego.

Plik Pojazd.h

class Pojazd
{
public:
    friend std::ostream& operator<< (std::ostream& o, Pojazd const& b);
    virtual void printOn(std::ostream& o) const = 0;
};

Plik Pojazd.cpp

inline std::ostream& operator<< (std::ostream& o, Pojazd const& b)
{
    b.printOn(o);
    return o;
}

Plik Samochod.h

class Samochod : public PojazdSilnikowy
{
public:
    virtual void printOn(std::ostream& o) const;
};

Plik Samochod.cpp

void Samochod::printOn(ostream &o) const
{
   cout << "Model " << model << "Kolor " << kolor; //nie jestem pewien czy to dobrze wypełniam
}

Dla klasy Rower robię analogicznie co dla klasy Samochód

Plik main.cpp


samochod1.printOn() // tutaj nie wiem co wpisac do nawiasu aby wyświetliło parametry 

2

Można to wywołać tak:

samochod1.printOn(std::cout);

Ale po to przeciążasz << aby z tego korzystać

std::cout << samochod1;

W rzeczy samej w tym idiomie (virtual friend function) zwykle chowa się te metody wypisujące jako chronione (przykład).

0

@Spearhead: Trochę się już zamieszałem i teraz widzę jaką głupotę chciałem zrobić, dzięki wielkie

Poprawiłem to zgodnie z tym co wysłałeś, jednak wciąż się nie kompiluje. Wyskakuje poniższy błąd:
screenshot-20211219185243.png

Moje kluczowe części kodu na ten moment wyglądają tak:

Plik main.cpp

Rower r1("kross", "bialy", 5000, 0, 0, false);
cout << r1;

Plik Pojazd.h

class Pojazd
{
public:
    Pojazd(std::string, std::string, float, float, int = 0);
    friend std::ostream& operator<< (std::ostream& o, Pojazd const& b);

protected:
    virtual void printOn(std::ostream& o) const = 0;
    std::string model, kolor;
    float cena, ladownosc; // [PLN], [l]
    int przebieg;
};

Pojazd.cpp

Pojazd::Pojazd(string model, string kolor, float cena, float ladownosc, int przebieg) : model(model), kolor(kolor),
cena(cena), ladownosc(ladownosc), przebieg(przebieg)
{
}

inline std::ostream& operator<< (std::ostream& o, Pojazd const& b)
{
    b.printOn(o);
    return o;
}

Rower.h

class Rower : public Pojazd
{
public:
    Rower(std::string, std::string, float, float, int, bool);
protected:
    virtual void printOn(std::ostream& o) const;


private:
    bool bagaznik;
};

Rower.cpp

Rower::Rower(string model, string kolor, float cena, float ladownosc, int przebieg, bool bagaznik)
: Pojazd(model, kolor,cena, ladownosc, przebieg), bagaznik(bagaznik)
{
    this->ladownosc = 0;
    if(bagaznik)
        this->ladownosc = 10;
}

void Rower::printOn(ostream &o) const
{
    cout << "M " << model << " K " << kolor << " C " << cena << " L " << ladownosc << " P " << przebieg << " B" << bagaznik << endl;
}
1

Zgaduję, że jeszcze musisz dodać Pojazd.cpp na liście plików kompilatora.

Przy okazji, to:

void Rower::printOn(ostream &o) const
{
    cout << "M " << model << " K " << kolor << " C " << cena << " L " << ladownosc << " P " << przebieg << " B" << bagaznik << endl;
}

nie jet poprawne, po to przekazujesz obiekt std::ostream, żeby go użyć, a nie na sztywno stosować std::count:

void Rower::printOn(ostream &o) const
{
    o << "M " << model << " K " << kolor << " C " << cena << " L " << ladownosc << " P " << przebieg << " B" << bagaznik << endl;
}
0

Zgaduję, że jeszcze musisz dodać Pojazd.cpp na liście plików kompilatora.>

#include załączam już "Pojazd.h" "Samochod.h" i "Rower.h" w pliku main.cpp. Gdy chce dodać tam #include "Pojazd.cpp" sypie błędami.

void Rower::printOn(ostream &o) const
{
    o << "M " << model << " K " << kolor << " C " << cena << " L " << ladownosc << " P " << przebieg << " B" << bagaznik << endl;
}

To również poprawiłem i wciąż ten sam błąd

0

#include robisz tylko dla plików nagłówkowych, natomiast pliki źródłowe przekazujesz do kompilatora (g++ main.cpp foo1.cpp foo2.cpp itd). Jako że używasz tam CMake więc dla niego musisz gdzieś w CMakeList.txt dodać Pojazd.cpp.>

Mój CMakeList wygląda tak:
screenshot-20211219192528.png

Mam w Pojeździe mam już inne metody, typu jedz(), tankuj() i one bez problemu działają.

1

Usuń słówko inline przed operatorem.

0

@_13th_Dragon: Dziękuje! :) już wczoraj otrzymałem tą rade w komentarzu i faktycznie pomogło

0

Mam jednak jeszcze jeden problem. Stworzyłem klasę Fabryka, a w niej wektor Parking w którym przechowuję utworzone pojazdy. Wektor został stworzony na pomocą wskaźnika inteligentnego. Gdy próbuję wyświetlić zawartość wektora za pomocą przeładowanego operatora<< wyskakuję mi błąd. Domyślam się, że może być to kwestia tego, że kod odpowiedzialny za przeładowanie nie pozwala na wysłanie do niego wskaźnika. Jednak próbowałem już dużo kombinacji i żadna mi nie działa. Ktoś coś doradzi?

Plik Fabryka.h

class Fabryka
{
public:
    Fabryka(float = 500000);
    void zamownie();
    void pokaz();
    void sprzedaj();
    void jazdaPojazdem();
    void tankowaniePojazdu();
    bool sprawdzId(int);

private:
    std::vector<std::unique_ptr<Pojazd>> parkingFabryka;
    float budzet;
};

Plik Fabryka.cpp

void Fabryka::pokaz()
{
    int ilosc = parkingFabryka.size();   //rozmiar wektora

    if (ilosc == 0)
        cout << "Twoja fabryka jest pusta" << endl;
    else
        for(int i = 0; i < ilosc; i++)
            cout << parkingFabryka[i];
            //parkingFabryka[i]->pokaz(); // TAK DZIAŁA, funkcja pokaz() wygląda tak: cout << "Model" << model << "Kolor" << kolor << .... i tak dalej.

    cout << "Budzet firmy " << budzet << "PLN" << endl;
}

Reszta kodu jest tak jak wyżej.

Błąd:
screenshot-20211220153110.png

i jeszcze parę linijek błędów jest, jeśli to konieczne to mogę dołączyć

1

cout << *(parkingFabryka[i]);

0

@_13th_Dragon: Działa! Byłem pewien, że ma to wyglądać podobnie, ale nie pomyślałem, że wymagany jest nawias i próbowałem robić to tak << *parkingFabryka[i];

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