Befogadás és öröklés

Tárgyak felvétele.

Két lehetőség van arra, hogy az X-es típusú objektumot az A osztályba vegye fel:

  1. Nyilatkozzanak az A. osztályba tartozó X típusú tagból;
  2. Egy A osztályban jelezzék az X * vagy X típusú elemeket.

Előnyös, ha a tényleges objektumot, mint az első esetben, magába foglalja. Ez hatékonyabb és kevésbé hibás, mivel a zárt és a benne található tárgyak közötti kapcsolatot az építési és megsemmisítési szabályok írják le.

A második változat a mutatóval akkor használható, ha a "tart" objektum élettartama alatt a mutatót a "zárt" objektumra kell változtatni.

A második lehetőség akkor használható, ha argumentumként a "zárt" objektumot kívánja megadni.

Ha objektumokat tartalmaz, amelyek más objektumokat tartalmaznak, létrehozunk egy objektum hierarchiáját. Ez egy alternatíva és az osztályhiergia mellett. És mi van akkor, ha a benne foglalt objektumok száma előzetesen ismeretlen és (vagy) megváltozhat a "tart" objektum élettartama alatt. Például ha az Iskola tárgya diákokat tartalmaz, akkor számuk változhat.

A probléma megoldására kétféleképpen lehet megoldani. Az első az, hogy a beillesztett objektumok összekapcsolt listáját szervezik, és a "tartalmi" objektumnak van egy tagmutatója a lista elejére.

Ebben az esetben az iskolai objektum létrehozásakor a mellékelt objektumok üres listáját hozza létre. Az objektum engedélyezéséhez az add () metódus nevezik. amely paraméterként átadja a mutatót a beillesztett objektumnak. A megsemmisítő egymás után törli az összes benne foglalt objektumot. A Person objektum a következő mezőt tartalmazza. amely lehetővé teszi objektumok összekapcsolását a listához.

A második módszer egy speciális tartály objektum használata.

A konténerosztályt objektumok tárolására tervezték, és kényelmes, egyszerű és kényelmes hozzáférést biztosít számukra.

A tartályok mellett vannak csoportok, azaz Olyan objektumok, amelyekben más objektumok szerepelnek. A csoporthoz tartozó objektumokat csoporttagoknak nevezik. A csoport elemei, viszont, lehetnek csoportok is.

  1. Egy olyan interaktív programban lévő ablak, amely olyan elemeket birtokol, mint az adatbevitel és a mezők szerkesztése, gombok, kiválasztási listák, párbeszédpanelek stb.
  2. Egy kisebb csomópontból álló egység.
  3. A növényekből, öntözőrendszerekből és növekvő tervből álló zöldségkert.
  4. Néhány szervezeti struktúra (például FACULTY, CHAIR, STUDENT GROUP).

A "csoport" és a "konténer" fogalma más. A tartályt más adatok tárolására használják. Konténer példa: az STL könyvtár konténerosztályainak tárgyai C ++-ban (tömbök, listák, sorok).

A konténerektől eltérően egy csoport olyan osztály, amely nemcsak más osztályok tárgyait tárolja, hanem saját tulajdonságai is vannak, amelyek nem követik az elemeinek tulajdonságait.

Csoport ad egy második nézete a hierarchia (az első fajta - osztály hierarchia épül alapján az öröklés) - objektum hierarchia (hierarchia egész típusú / rész), megépíteni alapján aggregációt.

A csoportot számos módon megvalósíthatja:

  1. A "csoport" osztály az objektumtípus adatmezeteit tartalmazza. Így a "csoport" objektum saját elemeket vagy mutatókat tartalmaz adatként. A csoport megvalósításának módját a C ++ Builder használja.
  2. A csoport az utolsó típusú TObject * tagot tartalmazza. amely a csoportba tartozó objektumok összekapcsolt listájának kezdetét jelzi. Ebben az esetben az objektumoknak egy következő TObject típusú mezővel kell rendelkezniük. jelezve a lista következő elemét.
  3. A TItem típusú struktúrák összekapcsolt listáját hoztuk létre. Az elem mező a csoportba tartozó objektumot jelöli. A csoport utolsó TItem * mezőt tartalmaz. amely a TItem típusú struktúrák összekapcsolt listájának kezdetét jelzi. Ha azt szeretné, hogy a csoporttagok elérhessék a mezőket és módszereket, a TObject típusú objektumnak TGroup * típusú tulajdonosi mezőt kell tartalmaznia. amely jelzi az elem tulajdonosát.

A csoport működéséhez két módszer szükséges:

Egy elem beillesztése egy csoportba.

Ezenkívül a csoport a következő módszereket tartalmazhatja:

Jelzi, hogy van-e legalább egy elem a csoportban.

Egy elem eltávolítása a csoportból, de a memóriában tárolja.

Eltávolít egy elemet a csoportból és a memóriából.

Az iterátorok lehetővé teszik, hogy bizonyos műveleteket végezzen egy adott adatkészlet egyes elemeihez.

Egy ilyen ciklus lehetne tenni az egész készlet, például az, hogy nyomtatni minden eleme egy sor, vagy kérhetik olyan elem, amely megfelel egy bizonyos feltétel, amely esetben ez a ciklus véget ér, amint a kért elem lesz megtalálható.

Az iterátorokat speciális osztálykategóriás módszerekként fogjuk figyelembe venni, amelyek lehetővé teszik, hogy bizonyos tevékenységeket végezzen a csoportba tartozó összes objektum számára. Az iterátor egyik példája a Show mód.

Szeretnénk egy olyan iterátort, amely lehetővé tenné, hogy a csoport minden elemén elvégezzék a műveleteket, amelyeket nem az objektum egyik módszere határoz meg, hanem egy tetszőleges felhasználói funkciót. Ilyen iterátort lehet végrehajtani, ha ezt a függvényt egy függvény mutatójának átadja.

Adja meg a mutató típusát a funkcióhoz az alábbiak szerint:

A funkciónak kötelező paramétere a TObject típusú vagy TObject *. amelyen keresztül egy objektumot továbbítanak neki, amelyhez bizonyos műveletek végrehajtásához szükséges.

Az iterátor módszer a következőképpen nyilvánul meg:

ahol a művelet az egyetlen szükséges paraméter-mutató egy olyan függvényre, amelyet a csoport minden egyes elemére felszólítanak; további paraméterek - a hívott funkcióhoz átvihető paraméterek.

Ezután egy funkciómutatót definiálnak és inicializálják az iterátoron átadott függvénynek.

Ezután az iterátort például egy további típusú paraméterként hívják meg. az alábbiak szerint:

Itt gr egy objektumcsoport.

Tekintsük az öröklés és a befogadás közötti kapcsolatot.

Befogadás és öröklés.

Legyen D osztály egy származtatott osztály a B. osztályból.

A D osztályú fejlécben nyilvános szó nyílt örökségre utal. Nyitott örökség azt jelenti, hogy a kapott D osztály a B. osztály altípusa. a D objektum szintén egy B. objektum. Ez az öröklés egy egy-egy kapcsolat vagy azt mondja, hogy D a D változata. Néha úgy is nevezik, hogy az interfész öröklés. Az örökség megnyitásakor a származtatott osztály változója az alap osztálytípus változójaként kezelhető. A mutató, amelynek típusa "mutató egy alaposztályhoz", olyan objektumokra mutathat, amelyek származtatott osztálytípussal rendelkeznek. Az örökség használatával osztályhierarzt építünk.

Tekintsük a következő osztályhierargiát.

Ezeket az osztályok tárgyait mutató mutatókat definiáljuk.

Hozz létre objektumokat ezekhez az osztályokhoz.

Tegyük fel, hogy a D osztályban van egy B. osztályú tag.

Másfelől a B osztályban van egy C. osztályú tag

Az ilyen befogadásnak egy has-a viszonyt kell neveznie. Az inklúzió használatával objektumok hierarchiáját hozhatjuk létre.

A gyakorlatban problémát jelent az öröklés és a befogadás közötti választás. Tekintsük az "Airplane" és a "Engine" osztályokat. A kezdők sokszor eszükbe jutnak, hogy a "motor" "repülőgép" származékát hozzák létre. Ez nem igaz, hiszen a repülőgép nem motor, motorja van. Az egyik módja annak, hogy látni kell, hogy vajon egy repülőgép több motorral rendelkezik. Mivel ez lehetséges, használnunk kell a felvételt, nem pedig az öröklést.

Tekintsük a következő példát:

Miért hibás az 1. és a 3. sor?

Az 1. sorban nincs D * átalakítás B * -ra.

A 3. sorban D nem rendelkezik g () értékkel.

Ezzel szemben az állami öröklés, nincs implicit konverzió egy osztály egyik tagját, és egy osztály, amely tagja egy másik osztály, nem helyettesíti a virtuális függvények az osztály.

Ha nyílt örökséget használ a D osztályhoz

nem tartalmaz hibákat.

Mivel D egy B. osztályból származtatott osztály, akkor implicit átalakulást hajtunk végre D-ből, következésképpen a B és D közötti megnövekedett függőség.

Vannak olyan esetek, amikor örökséget szeretsz, de nem engedheted meg ilyen átalakulást.

Például újra szeretnénk használni az alap-osztálykódot, de nem számítunk arra, hogy a származtatott osztály objektumokat az alap osztály példáinak tekintjük. Az örökségtől csak a kód újrahasználatát szeretnénk. A megoldás itt a magántulajdon. A zárt örökség nem egy altípusú kapcsolat, vagy pedig egy kapcsolat. Mi fogjuk hivatkozni rá, mint egy hasonló (vagy hasonló) vagy öröklés végrehajtását, szemben az örökölt a felület. A zárt (valamint a biztonságos) öröklés nem hoz létre típusú hierarchiát.

A tervezési szempontból a magántulajdonlás egyenértékű azzal, hogy tartalmazza, kivéve a funkciók cseréjével járó problémát. E megközelítés fontos alkalmazása nyílt örökség az elvont osztályból, ugyanakkor zárt (vagy védett) örökség egy adott osztályból a végrehajtás képviseletére.

Egy példa. Bináris keresési fa

A bináris fa csomópontjai egy általános mutatót tartalmaznak az adatadatokhoz. Ez megfelel a mutató típusának a származtatott osztályba. A számláló mező tartalmazza az adatok ismételt előfordulásainak számát. Egy adott származtatott osztály esetében meg kell adnunk az comp függvényt egy adott származtatott típus értékének összehasonlításához. A insert () függvény a csomópontokat a fában helyezi el.

A TP kereső funkció (Node * r, TP d) keresi a szubréteget a gyökér r-rel a d által képviselt információhoz.

A print () függvény egy szokásos rekurzió a bináris fa áthaladásához

Minden csomópont külső funkciót használ. print ().

Most hozunk létre egy származtatott osztályt, amely adatokat tárol a mutatókat char tagként.

A StringTree osztályban a beillesztési függvény a char * implicit konverzióját érvényteleníti *.

Az összehasonlító funkció comp így néz ki

A csomópontban tárolt értékek megjelenítéséhez használja a külső funkciót

Itt egy explicit, void * és char * típusú leadóra használjuk a cast operation type (type_name) kifejezést. A megbízhatóbb az operátor static_cast használata (TP).

Több öröklés

Az osztály lehet több közvetlen alap osztály

Ezt az örökséget plurálisnak nevezik. Többszörös öröklés esetén egyetlen osztály sem használható egyszerre egyszerre közvetlen alapként. Az osztály azonban többször is közvetett alap-osztály lehet.

Az osztályok (és objektumok) hierarchiája az alábbi:

Az osztály ismétlése megfelel több alap osztály objektumnak a származtatott objektumba való beillesztésébe. Ebben a példában két objektum van az X osztályban. Az esetleges kétértelműségek kiküszöböléséhez az X osztály egy meghatározott összetevőjére kell hivatkoznia, a teljes minősítéssel

A közvetett alaposztály objektumainak többszörös öröklésével történő duplikációjának kiküszöbölése érdekében ez az alaposztály virtuálisnak minősül.

Most az A osztály csak egy X példányt tartalmaz, amelyhez az Y és Z osztályok egyenlő jogokkal rendelkeznek.

itt
  • Az osztály osztályának tárgya 15 bájt memóriában foglalja el:
    • 4 bájt - az int mező;
    • 2 bájt - karakter mező;
    • 10 byte - a karakter mező [10];
  • az ABase osztály objektuma a memóriában 79 byte-ot foglal el:
    • 8 bájt - a kettős mező;
    • 15 bájt - bázisállomás;
    • 2 bájt - a virtuális osztályhierarchia kommunikációjához;
  • a BBase osztály objektuma 21 bájt memóriájában foglalja el:
    • 4 bájt - az úszómező;
    • 15 bájt - bázisállomás; 2 bájt - a virtuális osztályok hierarchiájában való kommunikációhoz;
  • objektum osztályba tartozó objektum h memóriából 35 bájt:
    • 4 bájt - hosszú mező;
    • 10 bájt - adat és ABase kommunikáció;
    • 6 bájt - érvényes és BBase;
    • 15 bájt - bázisállomás;

Ha a Base az ABase és a BBase osztályokban öröklődik, akkor az alap osztály nem virtuális, az resultb pedig:

  • A bázis objektuma 15 bájtot foglal el a memóriában
  • az ABase osztály objektum a memóriában 26 byte-ot foglal el (nincs 2 bájt a kommunikációhoz);
  • a BBase osztály célja 59 bájt memóriában (nincs 2 bájt a kommunikációhoz);
  • Objectv class Top a memóriában 46 bájt foglalja el (az alapobjektum kétszer lép be).

Helyi és beágyazott osztályok

Egy osztály egy blokk belsejében deklarálható, például egy függvénydefiníción belül. Ezt az osztályot helyinek hívják. Az osztályok lokalizálása azt jelenti, hogy az összetevők nem érhetők el az osztálydefiníciós területeken kívül (a blokkon kívül).

A helyi osztálynak nem lehet statikus adata, mert a helyi osztály összetevői nem definiálhatók az osztály szövegén kívül.

A helyi osztályon belül csak a típusnevek, a statikus változók, a külső változók, a külső függvények és a felsorolási elemek használhatók a környező osztályból. Ami tiltott, fontos megjegyezni az automatikus memória változóit. Van még egy fontos korlát a helyi osztályok számára: komponensfunkcióik csak beilleszthetők.

Egy osztályon belül megengedett meghatározni a típusokat, ezért egy osztályt le lehet írni egy másikban. Ezt az osztályot beágyazottnak nevezik. A beágyazott osztály helyi az osztályba, amelyen belül le van írva, és a helyi osztály használatának szabályai, amelyeket a fentiekben tárgyaltunk. Különösképpen azt kell mondani, hogy a beágyazott osztálynak nincs külön hozzáférési joga a zárt osztály tagjaihoz, vagyis csak az ilyen típusú objektumon keresztül férhet hozzá (csakúgy, mint a zárt osztályban nincs külön hozzáférési jog a beágyazott osztályhoz ).

Egy példa. "RECTANGLE" osztály.

Határozza meg a "téglalap" osztályt. Ebben az osztályban definiáld az osztályt beágyazott "cut" osztályként. A téglalap a szegmensekből épül fel.

Ezzel a technikával meghatározhat bármely geometriai alakot, amely egyenes szegmensekből áll.

A String osztály tárolja a karakterláncot C-terminált null karakterű tömbként, és referenciamérő mechanizmust használ a másolási műveletek minimalizálása érdekében.

A String osztály három helper osztályt használ:
  • StringRepeater. amely lehetővé teszi, hogy szétválaszthassa a String karaktert tartalmazó objektumok tényleges ábrázolását azonos értékekkel;
  • Tartomány - a tartomány túllépése esetén kivételt generál;
  • Referencia - olyan indexelési művelet végrehajtása, amely különbséget tesz az olvasási és írási műveletek között.

A többi taghoz hasonlóan a beágyazott osztály deklarálható az osztályban, de később meghatározható.

A String osztály a konstruktorok, a destruktorok és a hozzárendelési operátorok közös csoportját biztosítja.

Kapcsolódó cikkek