Öröklödési hiba

Öröklödési hiba
2021-01-05T18:37:02+01:00
2021-01-07T18:08:19+01:00
2022-08-12T00:12:27+02:00
lolvanplshelp
Sziasztok, egy kis segitséget kérnék öröklödés kapcsán. Van egy gépnyilvántartó program, amiben 3 tipusú gépjármű tárolható (busz,autó,munkagép) a probléma a vector elemeinek kiíratásánál kezdődik.

Itt az ősosztály (vastaggal kiemelve a metódus amelyikkel gond van):

class Autogepjarmu{ public: void setRendszam (string rendszam) {this->rendszam=rendszam;} void setTipus (string tipus) {this->tipus=tipus;} void setGyartasiev (int gyartasiev) {this->gyartasiev=gyartasiev;} string getRendszam() {return rendszam;} string getTipus() {return tipus;} int getGyartasiev() {return gyartasiev;} string ToString() { return "nemjo"; } protected: string rendszam; string tipus; int gyartasiev; private: };
Itt pedig egy gyerekosztály :

class MunkaGep: public Autogepjarmu { public: MunkaGep (string rendszam, string tipus, int gyartasiev, int kapacitas_kw, int igenybevetel_ora) { this->rendszam=rendszam; this->tipus=tipus; this->gyartasiev=gyartasiev; this->kapacitas_kw=kapacitas_kw; this->igenybevetel_ora=igenybevetel_ora; } string ToString() override { std::ostringstream oss; oss <<"A munkagep rendszama: " << rendszam << " ,tipusa: " << tipus << " ,gyartasieve: " << gyartasiev << "kapacitasa Kw-ban: " << kapacitas_kw << " ,igenybevetele oraban:" << igenybevetel_ora << endl; return oss.str(); }
Itt maga a creat eljárás van(nézétek el most hogy add, hibás az elnevezés) : 

Autogepjarmu Add() { cout << "Milyen tipust szeretnél, te sex machine ? Szamot irj!(1. Munkagep, 2. Teherauto 3. Busz)" << endl; string tipus_in; cin >>tipus_in; cout << "Mi a rendszama a jarmunek?"; string rendszam_in; cin >>rendszam_in; cout << "Mi a gyartasi eve?"; string gyartasiev_in; cin >> gyartasiev_in; string igenybevetel_in,kapacitas_in; if (tipus_in=="1") { cout<< "Mekkora a kapacitasa ? (Kw-ban)"; cin>> kapacitas_in; cout<< "Mekkora a heti összesített munkaóra ? "; cin>> igenybevetel_in; MunkaGep M (rendszam_in,tipus_in,stoi(gyartasiev_in),stoi(kapacitas_in),stoi(igenybevetel_in)); return M; } else if (tipus_in=="2") { cout<< "Mekkora a kapacitasa ? (Tonnaban)"; cin>> kapacitas_in; cout<< "Mekkora a heti futott km? "; cin>> igenybevetel_in; Teherauto T (rendszam_in,tipus_in,stoi(gyartasiev_in),stoi(kapacitas_in),stoi(igenybevetel_in)); return T; } else { cout<< "Mekkora a kapacitas? (Ferohelyek szama)"; cin>> kapacitas_in; cout<< "Mekkora a heti futott km? "; cin>> igenybevetel_in; Autobusz A (rendszam_in,tipus_in,stoi(gyartasiev_in),stoi(kapacitas_in),stoi(igenybevetel_in)); return A; } }



Itt pedig a listázás metódus és a main:

void DoList(vector <Autogepjarmu> AL) { vector <Autogepjarmu> :: iterator it; for(it = AL.begin(); it != AL.end(); ++it) { cout << (it)->ToString() << endl; } } int main() { vector <Autogepjarmu> AL; while(true) { string input; cout << "Valaszon az alabbi lehetosegek kozul!" << endl; cout << "1. * Ujabb auto adatainak tarolasa \n 2. Gepek adatainak teljes listazasa \n 3. Gep adatainak kiiratasa billentyuzetrol bekert rendszam alapjan \n 4. Igenybevetel összesitese kategoriankent \n 5. Kategoriankent szerviz igenybeveteli hatar beallitasa \n 6. Azoknak a jarmuveknek a listazasa, melyek a szerviz igenybeveteli hatart tulleptek. \n 7. Kilepes " << endl; cin >> input; if (input=="1") { system("cls"); Autogepjarmu lol = Add(); AL.push_back(lol); system("cls"); } else if(input=="2") { system("cls"); DoList(AL); } }
A probléma pedig az lenne, hogy a gyerek nem override-olja az ős ToString metódusát ezáltal amikor ki listáznánk az elemeket az ős ToString-et hívja meg. 
 

Valakinek van esetleg valami ötlete? 
Sokmindennel probálkoztunk már de egyikse vált be. :(
Mutasd a teljes hozzászólást!
Belefutottál az "object slicing" nevű gyönyörű C++-os jelenségbe.

Amikor a C++-ban valamit "Autogepjarmu"-nek deklarálsz, akkor abba csak pontosan Autogepjarmu típusú értéket rakhatsz, leszármazottat nem rakhatsz bele. Ennek a fő oka az, hogy statikusan foglalt le sizeof(Autogepjarmu) bájtot a változónak, amibe nem férne bele semmi olyan leszármazott példány, aminek több mezője van és ezért nagyobb a mérete. Ha mégis megpróbálod, akkor úgy oldja meg a problémát, hogy az Autogepjarmu mezőit feltölti a leszármazott példány megfelelő mezői alapján, a többi mezőt pedig eldobja, mivel azokat nem tudja hová rakni. A végeredmény nyilván az Autogepjarmu-ben definiált változatát hívja meg a metódusnak, mivel egy Autogepjarmu példányról beszélünk.

A megoldás az, hogy indirekciót kell bevezetned. Ez lehet Autogepjarmu*, Autogepjarmu&, vagy ezeket becsomagoló kényelmi típusok mint a unique_ptr. Mivel ezek nem közvetlenül tárolnak valamit, hanem csak mutatnak valamire, ők már meg tudják oldani hogy bizonyos esetben Autogepjarmu példányra mutassanak és időnként MunkaGep példányra. Ebben az esetben viszont a virtuális destruktor definiálása nagyon nagyon erősen ajánlott. (Ha pontosan tudod hogy mit csinálsz akkor bizonyos esetekben el tudod kerülni, de kezdőként nem ezzel akarod bonyolítani az életedet )

(Ja és a fent elmondottak ugyanúgy igazak a vector<Autogepjarmu> típusra is, vagyis a benne tárolt elemek csak pontosan Autogepjarmu típusúak lehetnek. Ha leszármazottakat is kell tárolnia adatvesztés nélkül, akkor már vector<Autogepjarmu*> vagy hasonló fog kelleni.)

szerk: Megint lassú voltam
Mutasd a teljes hozzászólást!

  • A függvény csak akkor lesz virtuális, ha használod a 'virtual' keyword-ot a deklarációjánál!
    Amúgy ez lefordult, mert ha nem virtuális függvényt próbálsz overrideolni, annak minimum jó nagy warning-nak kellene lennie..
    Mutasd a teljes hozzászólást!
  • Bocsi a figyelmetlenségért, véletlen kimaradt a virtual kulcsszó a beilesztett kódból, de úgy sem igazán müködik a dolog... :/ de köszi a választ
    Mutasd a teljes hozzászólást!
  • Légy szíves, akkor a helyes programot idézd be, de a legjobb lenne, ha előbb ellenőriznéd, hogy warning-mentesen forduljon. (Nem, nem a warningok letiltásával, hanem a kijavításukkal kell ezt elérni.)
    Mutasd a teljes hozzászólást!
  • Autogepjarmu Add()
    Object slicing körül nézz szét. Érték szerint visszatérve nem lesz jó..
    Mutasd a teljes hozzászólást!
  • Belefutottál az "object slicing" nevű gyönyörű C++-os jelenségbe.

    Amikor a C++-ban valamit "Autogepjarmu"-nek deklarálsz, akkor abba csak pontosan Autogepjarmu típusú értéket rakhatsz, leszármazottat nem rakhatsz bele. Ennek a fő oka az, hogy statikusan foglalt le sizeof(Autogepjarmu) bájtot a változónak, amibe nem férne bele semmi olyan leszármazott példány, aminek több mezője van és ezért nagyobb a mérete. Ha mégis megpróbálod, akkor úgy oldja meg a problémát, hogy az Autogepjarmu mezőit feltölti a leszármazott példány megfelelő mezői alapján, a többi mezőt pedig eldobja, mivel azokat nem tudja hová rakni. A végeredmény nyilván az Autogepjarmu-ben definiált változatát hívja meg a metódusnak, mivel egy Autogepjarmu példányról beszélünk.

    A megoldás az, hogy indirekciót kell bevezetned. Ez lehet Autogepjarmu*, Autogepjarmu&, vagy ezeket becsomagoló kényelmi típusok mint a unique_ptr. Mivel ezek nem közvetlenül tárolnak valamit, hanem csak mutatnak valamire, ők már meg tudják oldani hogy bizonyos esetben Autogepjarmu példányra mutassanak és időnként MunkaGep példányra. Ebben az esetben viszont a virtuális destruktor definiálása nagyon nagyon erősen ajánlott. (Ha pontosan tudod hogy mit csinálsz akkor bizonyos esetekben el tudod kerülni, de kezdőként nem ezzel akarod bonyolítani az életedet )

    (Ja és a fent elmondottak ugyanúgy igazak a vector<Autogepjarmu> típusra is, vagyis a benne tárolt elemek csak pontosan Autogepjarmu típusúak lehetnek. Ha leszármazottakat is kell tárolnia adatvesztés nélkül, akkor már vector<Autogepjarmu*> vagy hasonló fog kelleni.)

    szerk: Megint lassú voltam
    Mutasd a teljes hozzászólást!
  • Köszönöm a válaszokat, és köszönöm megoldódott a probléma :) !
    Mutasd a teljes hozzászólást!
abcd