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.