Ficsor Lajos Objektumok inicializálása CPP4 / 1 Objektumok inicializálása Ficsor Lajos Miskolci Egyetem Általános Informatikai Tanszék
Ficsor Lajos Objektumok inicializálása CPP4 / 2 Tartalom public adattagok inicializálása felsorolással konstruktor objektum tömbök osztály típusú tagok tagonkénti inicializálás inicializálás a származtatás során
Ficsor Lajos Objektumok inicializálása CPP4 / 3 Adattagok inicializálása felsorolással 1. class szemely { // CPPEX17 public: // Most a példa kedvéért!! char* nev; int szulev; public: void kiir (void) {cout << " \n" << nev << szulev; }; };
Ficsor Lajos Objektumok inicializálása CPP4 / 4 Adattagok inicializálása felsorolással 2. main() { szemely valaki = {"todor", 1937}; valaki.kiir(); } Analóg a struktúrák inicializálásával
Ficsor Lajos Objektumok inicializálása CPP4 / 5 Inicializálás konstruktorral Már ismert konstrukció Megjegyzések: Több konstruktor is megadható ez függvény overloading, tehát a fordító a megadott paraméter szignatúra alapján választ private konstruktor: csak a tagfüggvények és a friend osztályok érhetik el. protected konstruktor: csak a leszármazott és a friend osztályok érhetik el
Ficsor Lajos Objektumok inicializálása CPP4 / 6 Objektum tömbök Alapeset: a tömb minden elemére meghívódik a default konstruktor (amely átdefiniálható!) Inicializációs lista: a lista minden eleme egy konstruktor hívás kijelölése Egy paraméteres konstruktor esetén a paraméter megadása elegendő Ha a lista kevesebb elemet tartalmaz, mint a tömb, a maradék elemekre a default konstruktor hívódik meg Dinamikusan deklarált tömb esetén ( new ) a default kontruktor hívódik meg minden elemre.
Ficsor Lajos Objektumok inicializálása CPP4 / 7 Objektum tömbök - példa class szemely { char* nev; int szulev; public: szemely (char* ki, int mikor) { nev = new char [strlen(ki) + 1]; strcpy(nev, ki); szulev = mikor; } void kiir (void) {cout << " \n" << nev << szulev; } };
Ficsor Lajos Objektumok inicializálása CPP4 / 8 Objektum tömbök - példa (folyt.) main() { szemely szulok[]={ szemely("Kiss Lajos", 1950), szemely("Kiss Bea",1955)}; szulok[0].kiir(); szulok[1].kiir(); szemely nagyszulok[2]={ szemely("Nagy Bela", 1930) }; //nagyszulok[1].kiir(); hibás! }
Ficsor Lajos Objektumok inicializálása CPP4 / 9 Osztály típusú adattagok Tisztázandó kérdések: Konstruktorok végrehajtási sorrendje Először a tagosztály(ok) Utána a tartalmazó osztály A szabály rekurzív módon ismétlendő, ha szükséges Paraméter átadás a tagosztály konstruktorának Taginicializációs lista: a tartalmazó osztály definíciójának argumentumlistája után vesszővel elválasztott lista Az alaptípusú adattagok is megjelenhetnek a listán
Ficsor Lajos Objektumok inicializálása CPP4 / 10 Osztály típusú adattagok - példa class szemely { char* nev; int szulev; public: szemely (char* ki, int mikor) {.... }; void kiir (void) {.... }; };
Ficsor Lajos Objektumok inicializálása CPP4 / 11 Osztály típusú adattagok - példa (folyt.) class gyerek { char* neve; int szuletett; szemely anya; public: gyerek (char* nev, int ev, char* anyaneve, int anyaszuleve) : anya (anyaneve,anyaszuleve) {neve = new char[strlen(nev)+1]; strcpy(neve, nev); szuletett = ev; };
Ficsor Lajos Objektumok inicializálása CPP4 / 12 Osztály típusú adattagok - példa (folyt.) // Másik lehetséges változat // gyerek (char* nev, int ev, // char* anyaneve, int anyaszuleve) // : anya (anyaneve,anyaszuleve), // szuletett(ev) // { // neve = new char[strlen(nev)+1]; // strcpy(neve, nev); // };
Ficsor Lajos Objektumok inicializálása CPP4 / 13 Osztály típusú adattagok - példa (folyt.) void kiir (void) {cout << " \nGyerek neve, szuletesi eve:" << neve << szuletett; cout << "\nAnyja neve,szul. eve:"; anya.kiir(); }; };
Ficsor Lajos Objektumok inicializálása CPP4 / 14 Osztály típusú adattagok - példa (folyt.) main() { gyerek kisgyerek("Toth imre", 1994,"Kiss Bea",1970); kisgyerek.kiir(); }
Ficsor Lajos Objektumok inicializálása CPP4 / 15 Tagonkénti inicializálás Egy objektum inicializálása azonos típusú másik objektummal Ekkor nincs hagyományos konstruktorhívás! Nem azonos az objektumok közötti értékadással. Két fázisa: Létrejön az új objektum Automatikus kezdőértékadás történik
Ficsor Lajos Objektumok inicializálása CPP4 / 16 Tagonkénti inicializálás előfordulásai közvetlen inicializálás érték szerint átadott osztály típusú paraméter osztály típusú viszatérési érték Egyéb, közvetett módon létrejövő ideiglenes objektumok (konverzió, kifejezés kiértékelésének részeredménye, kivétel objektum stb.) A fentiekből következik: Soha nem lehetünk biztosak benne, hogy a programban nem történik ilyen inicializálás!
Ficsor Lajos Objektumok inicializálása CPP4 / 17 A másoló (copy) konstruktor A fordítóprogram az X osztály objektumainak tagonkénti inicializálására a X::X(const X&) speciális konstruktort (copy konstruktort) hívja meg. Ennek alapértelmezése: tagonkénti inicializáció Ez nem mindig megfelelő, ezért saját verzió definiálható Saját copy konstruktor esetén speciális szabályok
Ficsor Lajos Objektumok inicializálása CPP4 / 18 Tagobjektum és a copy konstruktor Két eset vizsgálandó A tartalmazó osztálynak nincs copy konstruktora: ekkor alapértelmezés szerint tagonkénti inicializálás történik minden adattagra, azaz A tag objektum a copy konstruktorával inicializálódik, ha rendelkezik ilyennel A tag objektum az alapértelmezés szerinti tagonkénti értékadással inicializálódik egyébként
Ficsor Lajos Objektumok inicializálása CPP4 / 19 Tagobjektum és a copy konstruktor (folyt.) A tartalmazó osztálynak van copy konstruktora: nem az alapértelmezés szerinti inicializálás történik A tartalmazó osztály copy konstruktora köteles gondoskodni a tagobjektumok inicializálásáról, taginicializációs listával Ha nincs a listán egy tagobjektum, akkor az alapértelmezés szerinti (tagonkénti) inicializálás történik, akkor is, ha a tagosztálynak van copy konstruktora!
Ficsor Lajos Objektumok inicializálása CPP4 / 20 Tagobjektum inicializálása - példa class szemely { char* nev; int szulev; public: szemely (char* ki, int mikor){...}; szemely (const szemely& sz) {nev=new char[strlen(sz.nev)+1]; strcpy (nev, sz.nev); szulev = sz.szulev; }; void kiir (void) {... }; };
Ficsor Lajos Objektumok inicializálása CPP4 / 21 Tagobjektum inicializálása - példa (folyt.) class gyerek { char* neve; int szuletett; szemely anya; public: // Normál konstruktor gyerek (char* nev, int ev, char* anyaneve, int anyaszuleve) : anya (anyaneve,anyaszuleve) { neve = new char[strlen(nev)+1]; strcpy(neve, nev); szuletett = ev; };
Ficsor Lajos Objektumok inicializálása CPP4 / 22 Tagobjektum inicializálása - példa (folyt.) class gyerek { char* neve; int szuletett; szemely anya; public: // Másik konstruktor gyerek (char* nev, int ev, szemely anyja) : anya (anyja) { neve = new char[strlen(nev)+1]; strcpy(neve, nev); szuletett = ev; };
Ficsor Lajos Objektumok inicializálása CPP4 / 23 Tagobjektum inicializálása - példa (folyt.) // Helytelen copy konstruktor gyerek ( const gyerek& gy) {neve = new char [strlen(gy.neve)]; strcpy (neve, gy.neve); szuletett = gy.szuletett; // Ez a hibás, mert nem copy konstruktorral inicializálódik!! anya = gy.anya; };
Ficsor Lajos Objektumok inicializálása CPP4 / 24 Tagobjektum inicializálása - példa (folyt.) // A helyes valtozat (explicit // inicializalassal): gyerek ( const gyerek& gy) : anya(gy.anya) {neve = new char [strlen(gy.neve)]; strcpy (neve, gy.neve); szuletett = gy.szuletett; }; Teljes verzió: CPPEX22.CPP
Ficsor Lajos Objektumok inicializálása CPP4 / 25 Inicializálás a származtatás során A származtatott osztálynak nincs copy konstruktora Alapmódszer a tagonkénti inicializálás Az a bázisosztály, amelynek van copy konstruktora, azzal inicializálódik A származtatott osztálynak van copy konstruktora A származtatott osztály copy konstruktorának kell meghívnia a bázisosztály copy konstruktorát, ha van Egyébként tagonkénti inicializálás, akkor is, ha a bázisosztálynak van copy konstruktora
Ficsor Lajos Objektumok inicializálása CPP4 / 26 Objektumok közötti értékadás A fordító az azonos ( X ) típusú objektumok közötti értékadást a const X& operator= (const X&) tagfüggvénnyel végzi. Alapértelmezése: tagonkénti értékadás Saját verzió definiálható Ha a copy konstruktorból saját verzió szükséges, akkor az értékadás operátorból is!
Ficsor Lajos Objektumok inicializálása CPP4 / 27 Értékadó operátor - példa class szemely { char* nev; int szulev; public: // Egyszerű konstruktor szemely (char* ki, int mikor); // Copy konstruktor szemely (const szemely& sz); // Értekadás const szemely& operator=(const szemely& sz); void kiir (void) const; };
Ficsor Lajos Objektumok inicializálása CPP4 / 28 Értékadó operátor - példa (folyt.) const szemely& szemely::operator=(const szemely& sz){ if (this != &sz) { // Nem azonosak delete [] nev; // Regi ertek torlese nev = new char [ strlen(sz.nev)+1 ]; strcpy (nev, sz.nev); szulev = sz.szulev; } return *this; };