30
Ficsor Lajos A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 1 Osztálytervezés Osztálytervezés Ficsor Lajos Miskolci Egyetem Általános Informatikai Tanszék

Osztálytervezés

Embed Size (px)

DESCRIPTION

Osztálytervezés. Ficsor Lajos Miskolci Egyetem Általános Informatikai Tanszék. Osztály tervezés. Egy nyelv szabályrendszere számos konstrukciót megenged A software fejlesztés során egy adott problémát kell megoldani - PowerPoint PPT Presentation

Citation preview

Page 1: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 1

OsztálytervezésOsztálytervezés

Ficsor Lajos

Miskolci Egyetem

Általános Informatikai Tanszék

Page 2: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 2

Osztály tervezésOsztály tervezés

Egy nyelv szabályrendszere számos konstrukciót megenged

A software fejlesztés során egy adott problémát kell megoldani

Szükséges tanulmányozni, hogy adott cél elérése érdekében milyen nyelvi szerkezet használata a legcélszerűbb

Page 3: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 3

Információ rejtésInformáció rejtés

A jól tervezett osztály belső részleteinek ismerete szükségtelen a használatához

Interface: a public tagfüggvények összességeezt kell ismernie az osztály használójának

a leszármazott osztály se tételezzen fel implementációs részleteket a bázisosztályáról

Page 4: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 4

A jó osztály interface 1.A jó osztály interface 1.

Teljesminden funkciót tartalmaz, ami az osztálytól elvárható

nem az adott alkalmazás szempontjai határozzák meg

újrafelhasználható egység

Minimálisnem tartalmaz a felhasználó számára érdektelen (esetleg veszélyes) elemeket

belső felhasználású funkciók private vagy protected minősítésűek

a belső áttervezés nincs rá hatással

Page 5: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 5

A jó osztály interface 2.A jó osztály interface 2.

Kezelhető méretűáltalában legfeljebb néhány tíz metódus

A sok funkció között nagyobb valószínűséggel lesznek hasonlóak (félreértés veszélye!)

A terjedelmes interface általában tervezési hibára utal:Az interface része belső funkció is

Az osztály határait nem jól állapítottuk meg, és túl sok feladatot akarunk rábízni. A helyes architektúra kialakítása érdekében az eredetileg tervezett osztályt több osztályra kell bontani, és ezek között leszármaztatással vagy más mechanizmussal megteremteni a kapcsolatot.

Page 6: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 6

Az osztály interface részeiAz osztály interface részei

Kezelő függvényekinicializáló, értékadó, konverziós stb. függvények

sokszor nem is a felhasználó program, hanem a fordítóprogram implicite hívja meg.

Elérési függvényekAz adattagok értékének elérésére vagy azok értékének módosítására.

Munkavégző függvényekAz osztály lényegi funkcióit aktivizáló függvények.

Page 7: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 7

Kezelő függvényekKezelő függvények

A kezelő függvények kialakítása az osztály használhatóságát alapvetően befolyásolja

Egyes kezelő függvények hiánya vagy helytelen implementációja a jól implementált munkavégző függvények ellenére is programhibákhoz vagy hibás működéshez vezethet

Page 8: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 8

Kezelő függvények tervezésének szempontjai 1.Kezelő függvények tervezésének szempontjai 1.

Hogyan kell az objektumoknak létrejönniük és megszűnniük?

konstruktorok száma, paraméterlistájuk

a desktruktor működése

a new és delete operátorok esetleges átdefiniálásának szükségességét.

Miben különbözik egy objektum inicializálása és értékadása?

A konstruktorok és az értékadó operátor működése.

Page 9: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 9

Kezelő függvények tervezésének szempontjai 2.Kezelő függvények tervezésének szempontjai 2.

Milyen kezdőállapoto(ka)t vehet fel egy objektum a keletkezése után?

valamennyi tagfüggvény implementációját befolyásolja, hogy milyen állapotot tételezhet fel, illetve köteles ellenőrizni.

Hogyan történik az objektumok érték szerinti átadása?

A copy konstruktor tervezéséhez.

Page 10: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 10

Kezelő függvények tervezésének szempontjai 3.Kezelő függvények tervezésének szempontjai 3.

Milyen legális értékeket vehet fel az osztály egy objektuma?

A tagfüggvények hibaellenőrzését befolyásolja.

Van bázisosztálya az új osztálynak?Mely funkciók örökölhetők változatlanul?

Vannak-e a bázisosztályban olyan virtuális függvények, amelyeket át kell definiálni?

Vannak-e a bázisosztályban olyan függvények, amelyeket felül kell definiálni?

Page 11: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 11

Kezelő függvények tervezésének szempontjai 4.Kezelő függvények tervezésének szempontjai 4.

Lesz-e várhatóan az osztálynak leszármazott osztálya?

Mely tagfüggvények, esetleg adattagok legyenek protected minősítésűek?

Melyek azok a funkciók, amelyeket a leszármazott osztályoknak át kell definiálni, azaz itt virtuálisnak célszerű minősíteni?

Page 12: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 12

Kezelő függvények tervezésének szempontjai 5.Kezelő függvények tervezésének szempontjai 5.

Milyen típusú konverziók megengedettek, illetve hasznosak?

Az általunk deklarált konverziós operátorokat a fordító a szükséges helyzetekben implicite (kifejezett kérésünk nélkül) is használni fogja.

Az implicit konverziót elkerülhetjük azáltal, hogy bizonyos konverziókat egyszerű tagfüggvények formájában fogalmazunk meg.

Érdemes gondolni arra, hogy az egyoperandusú konstruktor egyben konverziós operátor is!

Page 13: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 13

Kezelő függvények tervezésének szempontjai 6.Kezelő függvények tervezésének szempontjai 6.

Milyen operátorok definiálása lehet hasznos az osztály használatában?

Az operátor overloading tervezéséhez.

A felhasználó számára nem ajánlott, de az osztály implementációja számára hasznos operátorok definiálhatók private (esetleg protected) minősítéssel.

Page 14: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 14

Kezelő függvények tervezésének szempontjai 7.Kezelő függvények tervezésének szempontjai 7.

Miknek lehet szüksége a nem public tagok elérésére?

Mely adattagokat és tagfüggvényeket célszerű protected minősítéssel ellátni?

Mely osztályok illetve külső függvények kaphatják meg a friend minősítést?

Információ rejtésnek ellentmondó konstrukciók => gondosan elemzendő a szükségességük.

Különösen érdemes átgondolni, hogy a public adattag használata valóban elkerülhetetlen-e?

Page 15: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 15

Konstruktor tervezésének szempontjaiKonstruktor tervezésének szempontjai

A felhasználás kényelme

A konstruktornak konverziós szerepe is van!

Alapértelmezés szerinti konstruktor átdefiniálása szükséges-e?

copy konstruktor!

Page 16: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 16

Destruktor tervezésének szempontjaiDestruktor tervezésének szempontjai

Minden "mellékhatás" eltüntetése.

Bármilyen (legális) állapotban levő objektumra működnie kell!

Ha az osztály bázisosztály is lehet: a destruktornak nem kell-e virtuálisnak lennie?

Page 17: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 17

Operátorok tervezésének szempontjai 1.Operátorok tervezésének szempontjai 1.

Alapszabály: minden olyan operátort definiálni kell, ami az adott osztály használata során természetesnek tűnik.

Tervezési hiba, ha egy átértelmezett operátor jelentése a programozó számára nem egyértelmű. Különösen problémás egy, az operátor eredeti jelentésének ellentmondó jelentés definiálása.

Különleges szerepe van az = (értékadó) operátornak.

Page 18: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 18

Operátorok tervezésének szempontjai 2.Operátorok tervezésének szempontjai 2.

Ha egy relációs operátort értelmezünk, az összeset definiáljuk.

Sokszor hasznos lehet (és bármilyen típusú objektumra alkalmazható) az == és a != operátorok implementálása.

Nagyon sokszor hívott funkcióra kényelmes megoldás lehet a () - függvényhívás-operátor - átdefiniálása.

Page 19: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 19

Operátorok tervezésének szempontjai 3.Operátorok tervezésének szempontjai 3.

copy konstruktor, értékadás operátor és destruktor: két olyan műveletet, amelyeket azonosan kell implementálni:

az adattagok által használt memóriaterület felszabadítása ("destroy")

az adattagok másolása egyik objektumból a másikba ("copy").

Ezeket a műveleteket célszerű private tagfüggvény alakjában implementálni.

Page 20: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 20

Operátorok tervezésének szempontjai 4.Operátorok tervezésének szempontjai 4.

A segédfügvények felhasználásával:copy konstruktor: "copy"

értékadás: "destroy" + "copy"

destruktor: "destroy"

Page 21: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 21

Konstans tagfüggvények használata 1.

Minden olyan tagfüggvényt, amely nem változtatja meg az objektum állapotát, deklaráljunk konstans tagfüggvényként.

Konstans objektumra csak konstans tagfüggvény hívható meg.

Ha egy tagfüggvényből létezik const minősítésű és minősítetlen változat is, const objektumra const tagfüggvény hívódik meg.

Page 22: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 22

Konstans tagfüggvények használata 2.

Az, hogy egy tagfüggvény definíciója nem tartalmaz olyan utasítást, amely valamely adattag értékét közvetlenül megváltoztatja, még nem jelenti azt, hogy valamilyen közvetettebb módon nem változhat az objektum állapota.

Egy tagfüggvény számára a const minősítés megadásához gyakran a működésének a funkcionális elemzése szükséges.

Példa: CPPEX29

Page 23: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 23

Objektum átadása hivatkozás szerint 1.

Az érték szerint átadott paraméterek és visszatérési érték felesleges konstruktor, copy konstruktor és destruktor hívások.

Példa: CPPEX30.Cclass String {…}class Szemely {String nev;String cim;…}

Page 24: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 24

Objektum átadása hivatkozás szerint 2.

Szemely szemelyvissza1(Szemely sz){return sz;}Meghívása:

Szemely en("Ficsor", "Miskolc");

Szemely vissza("","");

vissza = szemelyvissza1(en);

Page 25: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 25

Objektum átadása hivatkozás szerint 3.

13 implicit függvényhívás!String copy konstruktorString copy konstruktorSzemely copy konstruktor

A formális paraméter inicializálása azaktuális paraméterrel

String copy konstruktorString copy konstruktorSzemely copy konstruktor

A return utasítás végeredményeinicializál egy ideiglenes objektumot

Szemely destruktorString destruktorString destruktor

Megszűnik a formális paraméter

Szemely ertekado operator A függvényértéket tartalmazóideiglenes objektum és a visszaváltozó közötti értékadás

Szemely destruktorString destruktorString destruktor

Megszűnik a függvény visszatérésiértékét tároló ideiglenes objektum

Page 26: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 26

Referencia objektum helyett 1.

Ne adjunk vissza referenciát, ha értéket kell visszaadni.

Ez gyakran érvénytelen hivatkozás visszaadását jelenti.

Page 27: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 27

Ne adjuk vissza lokális objektum címét 1.

Helyes implementáció:class Komplex {

double valos; double kepzetes;

public:

Komplex(double v, double k);

Komplex operator+(const Komplex& masik)

{return Komplex(valos + masik.valos, kepzetes+masik.kepzetes);

}

Page 28: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 28

Ne adjuk vissza lokális objektum címét 2.

Helytelen implementáció:

Komplex& operator+(const Komplex& masik)

{

Komplex eredmeny(valos + masik.valos, kepzetes+masik.kepzetes);

return eredmeny;

}

Hiba: megszűnt objektum referenciája!

Page 29: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 29

Ne adjuk vissza lokális objektum címét 3.

Másik helytelen implementáció:

Komplex& operator+(const Komplex& masik)

{

Komplex* eredmeny = new Komplex (valos + masik.valos, kepzetes+masik.kepzetes);

return *eredmeny

}

Hiba: ki szabadítja fel a lefoglalt helyet?

Page 30: Osztálytervezés

FicsorLajos

A C++ programozási nyelv 11. (Osztálytervezés) CPP11 / 30

Korlátozott láthatóságú adattag 1.Korlátozott láthatóságú adattag 1.

Egy tagfüggvény ne adja vissza olyan adattag referenciáját vagy pointerét, amelynek a láthatósága kisebb, mint a függvényé. Példa:

class String {

private:

char* elemek;

public:

operator char*() {return elemek;} //Hiba!

};