Előadást letölteni
Az előadás letöltése folymat van. Kérjük, várjon
1
A C++ programozási nyelv
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr.Dudás László 20./0. A C++ programozási nyelv Dinamikus foglalású tagokkal bíró objektumok kezelése Objektumok dinamikus foglalású adattagokkal Az operator = ( ) függvény megadása A String osztály
2
Objektumok dinamikus foglalású adattagokkal
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr.Dudás László 20./1. Objektumok dinamikus foglalású adattagokkal A C++ nyelvben az = operátor is átdefiniálható. Az alapértelmezése szerinti működés, miszerint a jobboldalán álló objektum statikus mezőit memóriaterület másolással átviszi a baloldalon álló balérték által azonosított címre, objektumba, csak addig alkalmazható, amíg a statikus adattagok között nincs olyan mutató, amely az objektum adattartalmához tartozó, de nem az objektum statikus területén tárolt adatra mutat. Az ilyen "függelékekkel" rendelkező objektumok tartalmának másolására, egymás közötti értékadására nekünk kell a megfelelő operator=() függvényeket megírni. Példánknál maradva, a nevek[ ] vektort dinamikusan a Heap memóriában foglaló konstruktorral és felszabadító destruktorral rendelkező Lista osztályunk objektumai pontosan ilyen egyedek. Heap Lista lista; int elemszam; nevek[ ] nevtip* nevek;
3
lista2 = lista1; // alapértelmezett = operátor // használatával
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr.Dudás László 20./2. Az alapértelmezett = operátorral történő értékadás nem másolná át a Heap memóriában lévő függeléket: Lista lista2; lista2 = lista1; // alapértelmezett = operátor // használatával int elemszam; 8 nevtip* nevek; Probléma: a lista1.nevek[ ] és a lista2.nevek[ ] ugyanaz, ha egyiket módosítom, a szándékommal ellentétesen a másik is módosul. Az egyik objektum törlésekor a destruktor felszabadítja a memóriaterületet, amit újabb foglalás felülírhat, elrontva ezzel a másik objektum számára a nevek[] tartalmát. Heap 4873 4873 Lista lista1; nevek[ ] int elemszam; 8 nevtip* nevek; 4873 lista2 eredeti vektora törölhetetlenül ott maradt a memóriában, mert a lista2.nevek mutatót az értékadás felülírta.
4
Lista2.operator=(lista1);
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr.Dudás László 20./3. Megoldás: A Lista osztály objektumai számára saját operator =( ) függvény, mely az értékadásnál gondoskodik a nevek[ ] vektor megduplázásáról. Lista2.operator=(lista1); Lista lista2; Heap int elemszam; 5912 8 nevek[ ] nevtip* nevek; Az operátornak köszönhetően az értékátadás után az azonos vektortartalmak megduplázódnak és önálló életet élnek. 5912 Lista lista1; int elemszam; 4873 8 nevtip* nevek; nevek[ ] 4873
5
Az operator = ( ) függvény megadása
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr.Dudás László 20./4. Az operator = ( ) függvény megadása class Lista {… public: Lista& operator = (Lista& masiklista); // deklaráció ... }; … Lista& Lista::operator = (Lista& masiklista) // definíció { if (this != &masiklista) // egyébként önmagának ad értéket lista2 = lista2; { delete [ ] nevek; // a régi tartalom, a függelék felszámolása, mintha destruktor lenne nevek = new nevtip[masiklista.elemszam]; // helyfoglalás a másoláshoz elemszam= masiklista.elemszam; // másolás az újba a másikból: for (int i= 0; i <elemszam; i++) strcpy(nevek[ i ], masiklista.nevek[ i ]); } return *this; // önmagát adja vissza }
6
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr.Dudás László 20./5. // az értékadás operátorfüggvény használata: Lista lista3(15), lista4(17); // definiálunk két lista objektumot void main( ) {… // a lista objektumok értéket kaphatnak itt lista4 = lista3; // = operátorral ... } Megjegyzések: Az operátorfüggvény bemenete és kimenete referenciával van átadva, ami objektumok esetén javasolt, hogy ne kelljen adatot mozgatni. Referencia átadása gyakorlatilag egy mutatóérték átadását jelenti. A legelső vizsgálat azért szükséges, hogy ha lista2=lista2; alakú ritkán használt értékadásban használjuk, akkor ne próbáljon az éppen törölt vektorból olvasni. Bár a Lista típusú objektumok értékátadását az operátor megoldja, az újonnan definiált objektum másik objektummal történő inicializálása további, hasonló gondot vet fel. A Lista lista1(23); … Lista lista2 = lista1; definiáláskori kezdőértékadás esetén a létrehozott = operátor nem működik, mert ezen a helyen az = jel inicializálást jelent.
7
public: Lista (Lista& masiklista); // copy konstruktor deklarációja
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr.Dudás László 20./6. A problémára a megoldást az alapértelmezett ún. copy konstruktor átdefini-álása jelenti. Ennek formája a Lista osztály esetén: class Lista {… public: Lista (Lista& masiklista); // copy konstruktor deklarációja ... }; … Lista :: Lista(Lista& masiklista) // definíció { nevek = new nevtip[masiklista.elemszam]; // helyfoglalás a másoláshoz elemszam= masiklista.elemszam; // másolás az újba a másikból: for (int i= 0; i <elemszam; i++) strcpy(nevek[ i ], masiklista.nevek[ i ]); } Megfigyelhetjük, hogy a copy konstruktor az operator= függvényből a kezdő azonosságvizsgálat, a destruktor feladatának megfelelő felszabadítást végző rész és az objektum visszaadásának elhagyásával adódik.
8
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr.Dudás László 20./7. Végül oldjuk meg az operátor többalakúság téma bevezetőjében említett összeadás operátor definiálási feladatot. A + operátortól azt várjuk, hogy két lista objektum között alkalmazva azok összefűzött alakját adja eredményül, mely eredményt az = operátorunknak köszönhetően egy harmadik lista objektum azonnal felvehet. Mivel a Lista osztályunk már nagyon sok függvényt tartalmaz, a dolgunk egyszerű lesz. class Lista {… public: Lista operator+(Lista& masiklista); // operator+() fv deklarációja ... }; … // ha már rendelkezésre állnak az operátorok, könnyűvé válik a programozás: void main( ) { … Lista l1(33), l2(22), l3(3); … l3= l1+ l2; ...} // alkalmazása Lista Lista :: operator+(Lista& masiklista) // definíció { Lista segedlista= *this; // létrehozás és inicializálás az első listával (copy konstruktor) segedlista+= masiklista; // hozzáfűzzük a második listát (operator+=() ) return segedlista; }
9
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr
Alkalmazott Informatikai Tanszék MŰSZAKI INFORMATIKA dr.Dudás László 20./8. A String osztály Az előzőekben megismertük azokat a lényegi tudnivalókat, amelyek dinamikus adatszerkezeteket is tartalmazó objektumok programozásához szükségesek. A Lista osztály és a hasonló dinamikus osztályok rugalmasan alkalmazkodnak a program futása során a tárolóhely igényekhez. Létrehozhatók a mutatott módon globális változóként, de blokkban lokális változóként és dinamikusan is létrehozhatjuk őket. A definiált operátoroknak köszönhetően a használatuk könnyűvé válik. Komolyabb C++ környezetekben rendelkezésünkre áll a String osztály. Egy string objektum ugyanolyan dinamikusan hosszát változtatni képes adatszerke-zettel rendelkező egyed, mint az előbb bemutatott Lista osztály példányai. Az osztályban definiálták mindazokat a szolgáltatásokat, operátorokat, amelyek egyáltalán szóba jöhetnek szövegek kezelésénél. A String osztály használatával elfeledhetjük a C nyelv karaktervektor szemléletet igénylő szövegváltozóit, mindezt a String osztály elrejti előlünk. A Pascal nyelv könnyedségével végezhetjük az értékadást, az összefűzést, a relációoperátorokkal történő összehasonlítást, stb. A C++ nyelvet igen gazdag osztálykönyvtár teszi hatékonyan alkalmazható programnyelvvé.
Hasonló előadás
© 2024 SlidePlayer.hu Inc.
All rights reserved.