Rövid gyik ac

[10.11] Mi a hiba a sorrendben statikus inicializálás ( „statikus inicializálás érdekében kudarc”)?

Észrevehetetlen és alattomos módon megölni a projekt.

Hiba statikus inicializálás érdekében - ez nagyon vékony, és gyakran félreértett aspektusa a C ++. Sajnos, az ilyen hiba nagyon nehéz elkapni, mert előfordul való belépés előtt a main () függvény.

Képzeljük el, hogy van két statikus objektumok x és y. amelyek két különböző forrás fájlokat, mondjuk x.cpp és y.cpp. És ahogy a tervező tárgy y eljárás tárgya x.

Ez minden. Ilyen egyszerű.

A probléma az, hogy van pontosan ötven százaléka lehetőségét katasztrófa. Ha ez megtörténik, a fordítási egység x.cpp indítja az első, minden rendben van. Ha az első indítja y.cpp fájlfordító akkor y objektum konstruktor előtte indul a kivitelező x. és akkor terjed ki. Ie y hatására a kivitelező módszer az objektum x. ha x önmagában még nem állapították meg.

Menj dolgozni a McDonalds. Tedd Big Mac, felejtsd osztályok.

Megjegyzés: A statikus inicializálási hibája nem vonatkoznak az alapvető / beépített típusok, például int vagy char *. Például, ha létrehoz egy statikus változó float típusú. akkor nem lesz probléma az inicializálási eljárást. A probléma csak akkor merül fel, ha a statikus vagy globális objektumok egy kivitelező.

[10.12] Hogyan kerülhető el a hibát a következő sorrendben: statikus inicializálás?

Az „ami az első használat”, hogy van, tegye a statikus objektumot a funkciót.

Képzeljük el, hogy van két osztály, Fred és Barney. Van egy globális típusú objektum Fred. x nevű. és a globális objektum típusok Barney, a imenemy. Barney kivitelező felhívja goBowling () módszer az objektum x. x.cpp fájl tartalmazza a meghatározása a tárgy x.

y.cpp fájl tartalmazza a meghatározása a tárgy y.

A teljesség kedvéért azt képzelni, hogy a tervező Barney :: Barney () a következő:

Amint a fentiekben leírtuk [10,11], az a probléma lép fel, ha Y jelentése generált x előtti. amely akkor esetek 50% -ában, mivel az X és Y jelentése különböző forrás fájlokat.

Számos megoldás erre a problémára, de az egyik nagyon egyszerű és hordozható - helyett a globális objektum Fredx. globális funkció x (). ami visszaadja a Fred objektum hivatkozásként típusát.

Ez az úgynevezett „létrehozása az első használat” globális Fred objektum jön létre az első alkalom, hogy elérhető.

A hátránya ennek a technikának az a tény, hogy Fred tárgy sohasem vész. Book of C ++ FAQ könyv leírja a kiegészítő berendezések, amely lehetővé teszi, hogy megoldja ezt a problémát (bár árán lehetséges hibák előfordulása nagyságrendű statikus visszavonás).

Megjegyzés: A statikus inicializálási hibája nem vonatkoznak az alapvető / beépített típusok, például int vagy char *. Például, ha létrehoz egy statikus változó float típusú. akkor nem lesz probléma az inicializálási eljárást. A probléma csak akkor merül fel, ha a statikus vagy globális objektumok egy kivitelező.

[10.13] Hogyan kell kezelni a hibákat a sorrendben inicializálása statikus objektumok - az osztály tagjai?

Használja ugyanazt a technikát leírtak [10.12], de ahelyett, hogy globális funkciók egy statikus tag függvény.

Tegyük fel, hogy egy osztály X. ahol van egy mozdulatlan tárgy Fred.

Természetesen ez a statikus tagja inicializálja külön kiemelve:

Ismét természetesen Fred objektumot fogják használni egy vagy több eljárás osztályú X.

A probléma mutatkozik, ha valaki valahol valahogy felhívja ezt a módszert, mielőtt a Fred objektum jön létre. Például, ha valaki létrehoz egy statikus X objektumot, és meghívja a someMethod () alatt a statikus inicializálás, akkor a sorsa teljesen a kezében a fordító, amely létrehozhat X :: x_. előtt someMethod () nevezzük. vagy pedig közvetlenül utána.

(Meg kell jegyeznem, hogy az ANSI / ISO C ++ bizottság dolgozik ezen a problémán, de fordítóprogramok, amelyek a munka szerint a legújabb változások, még nem állnak rendelkezésre, talán a jövőben ez a szakasz lesz a kiegészítés kapcsán a megváltozott helyzetet.)

Mindenesetre, akkor mindig a tolerancia (és ez teljesen biztonságos módszer) helyett statikus tag az X :: x_ statikus tag funkció:

Természetesen ez a statikus tagja inicializálja külön kiemelve:

Ezt követően, akkor egyszerűen változtatni x_ x ().

Megjegyzés: A statikus inicializálási hibája nem vonatkoznak az alapvető / beépített típusok, például int vagy char *. Például, ha létrehoz egy statikus változó float típusú. akkor nem lesz probléma az inicializálási eljárást. A probléma csak akkor merül fel, ha a statikus vagy globális objektumok egy kivitelező.

[10.14] Hogyan lehet kezelni a hibát, hogy történt a kivitelező?

Létrehoz egy kivétel. A részleteket lásd a [17.1].

A [11] és légkalapácsok

[11.1] Mi a destruktor?

Destructor - a teljesítése az utolsó lesz a tárgy.

A destruktor használják, hogy kiadja a források által elfoglalt objektumot. Például Lock osztály lezárhatjuk erőforrás kizárólagos használatára, és annak destructor felszabadítani az erőforrást. De legtöbbször ez a helyzet -, amikor a kivitelező használja az új. és a destruktor - törölni.

A destruktor függvénye „készíteni, hogy meghaljon.” Gyakran a szó destructor csökkenteni dtor.

[11.2] Milyen sorrendben hívják destruktorai helyi tárgyak?

A fordított sorrend, amelyben ezeket a tárgyakat hoztunk létre: az első - az utóbbit kell semmisíteni.

A következő példában, a destructor az objektum b lesz az úgynevezett első, és csak ezután a destructor egy objektum egy:

[11.3] A sorrend, amelyben destruktorok hívják a tömbök objektumok?

Fordított sorrendben a teremtés: az első - az utóbbit kell semmisíteni.

A következő példában, a sorrendben a hívás lesz ilyen destruktorok: a [9], a [8]. egy [1], a [0]:

[11.4] Lehet túl a destruktor az én osztály?

Minden osztálynak csak egy destruktor. Az osztály Fred, akkor mindig lehet nevezni Fred ::

Fred (). A destruktor nem jut el a paramétereket, és a destruktor soha nem tér vissza semmit.

Mindegy, akkor nem lenne képes meghatározni paramétereket a destruktor, mert soha nem hívja a destruktor közvetlenül [11,5] (pontosabban szinte soha [11,10]).

[11,5] Lehet kifejezetten meghívja a destruktor a helyi változó?

A destruktor neve továbbra is újra, amikor eléri a záró zárójel> a végén a blokk, amelyben a helyi változó jött létre. Ez a felhívás által biztosított nyelvi és ez automatikus; nincs módja, hogy megakadályozzák ezt a kihívást. De milyen következményekkel jár a visszahívás destruktor ugyanazon tárgy lehet végzetes. Ugyan! És halott.

[11.6] Mi van, ha szeretnék egy helyi változót a záró zárójel „halott”? Tudok a sürgősségi hívás a destruktor a helyi változó?

Nem! [Lásd a választ az előző kérdésre [11,5]].

Tegyük fel, hogy a (kívánatos) mellékhatása hívja a destruktor a helyi fájl célja, hogy zárja be a fájlt. És tegyük fel, hogy van egy példány a File osztály és f akarunk f fájl vége előtt lezárult a hatály (vagyis mielőtt>):

Erre a problémára van egy egyszerű megoldás, amit mutatni [11.7]. De eddig csak a következő megjegyzés: ne kifejezetten meghívja a destruktor [11,5].

[11.7] Nos, én nem kifejezetten meghívja a destruktor. De hogyan kezeljék ezt a problémát?

[Lásd még a válasz az előző kérdésre [11.6]].

Csak tegye a helyi változót egy külön mondatban. megfelelő az előírt élettartama változó:

[11,8] És mi van, ha nem tudok tenni egy változó egy egységet?

A legtöbb esetben, akkor egy további termékmintát, hogy korlátozza az idő az élet változó [11.7]. De ha valamilyen okból nem tud hozzáadni egy blokk, adjunk hozzá egy tag függvény, amely ugyanazt a műveletet, mint a destruktor. De ne feledd: nem tudja hívni a destruktor magad!

Például abban az esetben az osztály fájl. felvehet egy módszer close (). Semleges destruktor hívja close (). Megjegyezzük, hogy a close () metódus kell valahogy jelölje meg a lehetőség fájl. így a későbbi hívások megpróbálja bezárni a fájlt már lezárták. Például beállíthatja a tag változó fileHandle_ a fel nem használt érték, 1-es típusú, és ellenőrizni kell a korai, nem tartalmaz-e fileHandle_ -1.

Megjegyezzük, hogy a többi File osztály módszerek is ellenőrizni kell, hogy fileHandle_ értéke 1 (azaz, ha a fájl nem zárt).

Szintén fontos megjegyezni, hogy minden a tervezők, hogy ne nyissa meg a fájlt, telepíteni kell fileHandle_ -1.

[11.9] De én kifejezetten meghívja a destruktor az objektum jön létre az új?

Valószínűleg nem.

Kivéve abban az esetben, ha használja a végeredmény szintaxis szereplő új [11,10], akkor egyszerűen töröld tárgyak segítségével a törlés. helyett igénybevétele destructor kifejezetten. Tegyük fel, hogy létrehoz egy objektumot egy hagyományos, új:

Ebben az esetben, a romboló Fred ::

Fred () fog automágikusan hívni, ha törlöd az objektumot:

Nem kell kifejezetten meghívja a destruktor, mert nem szabad a lefoglalt memóriát a Fred objektumot. Ne feledje: törölni p két dolgot tesz [16,8], és felhívja a destruktor felszabadítja a memóriát.

[11.10] Mi az a „végeredmény szintaxis” új ( „elhelyezés új”), és miért van rá szükség?

Sok esetben használni az elhelyezés szintaxis új. A legegyszerűbb - akkor a végeredmény szintaxis forgalomba egy objektum egy adott helyen a memóriában. Ehhez meg kell adni a helyét, átadva a mutatót azt az üzemeltető új.

A vonal # 1 által létrehozott egy sor sizeof (Fred) bájt, a mérete, amely elegendő tárolására Fred objektumot. Összhangban # 2 létrehoz egy pointer helyen. amely rámutat, hogy az első byte array (tapasztalt C programozók talán észrevette, hogy nem tudja létrehozni az index, megcsináltuk, csak hogy a kód érthetőbbé [Mintha - :) YM]). Összhangban # 3 történik valójában csak hívja Fred :: Fred () konstruktor. Ez a mutató a Fred kivitelező egyenlő lesz a mutató helyre. Így a visszaadott mutató is egyenlő elhelyezni.

VESZÉLY: A végeredmény szintaxis új akkor teljes felelősséget vállal arra, hogy a mutató akkor telt jelzi, ha elegendő az objektum tárolására memória területet az összehangolás (kiigazítás), hogy szeretne a tárgyat. Nem fordítóprogram vagy a könyvtár nem helyességét ellenőrizni a tevékenységét, ebben az esetben. Ha az osztály Fred kell igazítani négy byte-os határt, de nem adtál az új index egy el nem kötelezett memóriahely, akkor lehet, hogy nagy baj (ha nem tudod, mit jelent a „beállítás” (kiigazítás), kérjük, ne használja a végeredmény szintaxis új ). Már figyelmeztettek.

Is, akkor viseli a felelősséget a pusztítás az objektum helyén levő. Ehhez kifejezetten meg kell hívni a destruktor:

Ez gyakorlatilag az egyetlen eset, amikor kifejezetten meg kell hívni a destruktor.

[11.11] Amikor írok egy dekonstruktorra van szükségem, hogy kifejezetten meghívja a destruktorai tagja tárgyak órámon?

Nem. Soha ne kifejezetten meghívja a destruktor (kivéve az elhelyezés szintaxis új [11,10]).

[11.12] Amikor írok egy származtatott osztály dekonstruktorra nem azt kell kifejezetten meghívja a destruktor őse van szüksége?

Nem. Soha ne kifejezetten meghívja a destruktor (kivéve az elhelyezés szintaxis új [11,10]).

A dekonstruktorának származtatott osztály (implicite létre a fordító, vagy kifejezetten Ön által leírt) automatikusan meghívja az destruktorok ősök. Ősök elpusztult pusztulása után a tag a származtatott osztály. Abban az esetben, többszörös öröklődés osztály közvetlen ősök elpusztult fordított sorrendben való megjelenésük az örökség listáján.

Megjegyzés: Abban az esetben, virtuális öröklési eljárás megszüntetését osztályok nehéz. Ha támaszkodik az eljárás megszüntetését osztályok esetében virtuális öröklés, akkor további információra van szüksége, mint tartalmaz ez a FAQ.

Kapcsolódó cikkek