A c

sablon

inline Típus * MP:: operátor -> () const

Így egy kis felmelegedés után az intelligens mutatók vezetővé váltak. Most a főzésünkben van még egy összetevő - a C + + fogantyú. Ne felejtsd el ezt a kifejezést a Macintosh és a Windows operációs rendszerekben használt leírásokkal. Vannak hasonlóságok, de a C ++ leírók idióma saját egyedi szemantikával és szabályokkal rendelkezik.

Az alapötlet az intelligens mutatók használata a vezető mutatókhoz. Ezeket a további mutatókat descriptoroknak nevezik. Az alap, amelyre a leíró kategóriát építjük, az első megközelítésben így néz ki:

sablon

MP operátor -> () const

A H nem-argumentum konstruktor új vezető mutatót hoz létre. Ez a vezető mutató viszont létrehozza a megadott objektumot. Van egy második konstruktor, amely megkapja a vezető mutatót és inicializálja a ptr változót. A példány konstruktor és a = operátor alapértelmezés szerint megfelelő, mivel lehet, hogy minden leíró számára több leíró. Az operátor -> művelet a fordító által használt rekurzív algoritmuson alapul: a -> leíró operátor visszaküldi a vezető mutatót; akkor a -> vezető pointer operátor visszaküldi a Type * mutatót, amely a fordító egyik alapvető típusa.

A fenti megoldás nem nevezhető elegáns - a beágyazott minták zavart okoznak, és teljesen világos, hogy mikor és hogyan lehet eltávolítani a vezető indexeket. Emellett lehetővé kell tennie, hogy a felhasználó közvetlenül hozza létre és szüntesse meg a vezető indexeket, vagy csatolja azokat a leíró kategóriákba, ahogyan a megadott objektumokat a vezető mutatókon belül befoglaljuk? Valóban dolgoztunk ezeken a problémák megoldására a hegyes tárgyaknál, majd újra szembenézünk a vezető mutatókkal? Türelem - időben megtaláljuk a választ ezekre és még sok más kérdésre.

Mi történik?

Kezdjük a vezető indexek egyszerű példájával, és olyan szintre emeljük, amely még az igényesebb közönséget is kielégíti. Ebben a szakaszban még mindig nehéz megérteni a deszkriptorok teljes előnyeit, de a következő fejezetekben nagyon fontos szerepet fognak játszani.

Objektumok számlálása

Tegyük fel, hogy nyomon szeretné követni egy létrehozott vagy a memóriában lévő osztályok számát. Az egyik lehetséges megoldás az, hogy ezeket az információkat az osztály statikus változóinak tárolja.

osztály CountedStuff

statikus int áram; nyilvános:

CountedStuff () CountedStuff (const CuntedStuff) CountedStuff operátor = (const CountedStuff)

<> // Ne változtassa meg a hozzárendelési számlálót

Ezzel a példával még mindig megcsodálhatja és javíthatja azt, de nem számít, mennyire keményen próbálkozol, meg kell változtatnia a célosztály kódját - legalább azért, hogy örökölhesse az osztályunkból. Tegyük fel, hogy a megadott objektum a kereskedelmi könyvtárba kerül. Ez szégyen, mi? A változások nem kívánatosak, de valószínűleg egyszerűen lehetetlenek. De itt jön a vezető index osztályzata.

sablon osztályú CMP

statikus int áram; Típus * ptr;

CMP (const CMP cmp). ptr (új típus (* (mp.t))) CMP operátor = (const CMP CMP)

ha (ez! = CMP)

ptr = új típus (* (cmp.ptr));

Most a vezető mutató elvégzi az összes számítást az Ön számára. Nem szükséges módosítani a megadott objektum osztályát. Ez a sablon bármelyik osztályhoz használható, feltéve, hogy az ügyfél és a megadott objektum között a vezető mutatókat szúrhatja be. Még ha nem bánod a módosítás az eredeti osztály a kijelölt objektumot, olyan szintű modularitás nélkül vezető mutatók rendkívül nehéz lenne (például ha megpróbálta a munka révén az alap osztály, az eredmény egy statikus változó aktuális minden származtatott osztály).

Ez a példa triviális, de még ő is azt mutatja, fontos elve, programozás C ++, amelynek érvényességét végül nyilvánvalóvá válik: az intelligens mutató, még ha elsőre úgy tűnik, hogy nincs rájuk szükség. Ha a program okos mutatókra van írva, minden változtatás könnyen és gyorsan történik. Ha újra kell készíteni a kész programot, és cserélni kell az összes operátort intelligens mutatókkal, készüljön fel az éjszakai ébresztésre.

A 14. fejezetben a számlálási téma változatait egy egyszerű, de hatékony memóriakezelő rendszer, a szemétgyűjtés és referenciaszámlálás végrehajtására használják.

Csak olvasható mutatók

Tegyük fel, hogy bizonyos objektumokat soha nem frissítünk (vagy legalábbis rendszeres ügyfelek nem frissítenek). Ez a probléma könnyen megoldható a vezető indexek segítségével

- elegendő, hogy az operátor -> () operátor működése az osztály állandó funkciója legyen.

sablon

ROMP operátor = (const ROMP); const Típus * operátor -> () const;

A megadott objektumot olyan megbízhatóan zárják, hogy még a CIA sem érheti el. Elvileg ugyanezt lehet tenni egyszerűbb intelligens mutatókkal, de a vezető mutatók 100% -os védelmet nyújtanak, mivel az ügyfél soha nem kap közvetlen hozzáférést a megadott objektumhoz.

Mutató az olvasáshoz / íráshoz

Sok esetben az objektum optimális ábrázolása van, amely csak az olvasási műveletekre érvényes. Ha az ügyfél módosítani kívánja az objektumot, módosítania kell a nézetet.

Ez könnyen elvégezhető, ha az operátor két, túlterhelt verziója van ->. amelyek közül az egyik a Foo * -t adja vissza. és a másik const Foo *. Sajnálatos módon a különböző visszatérési típusok nem nyújtanak aláírások egyediségét, így ha két operátort próbálnak kijelenteni - a fordító szívesen nevetni fog. A programozónak előzetesen hívnia kell egy olyan funkciót, amely az előadásról egy másikra való áttérést hajt végre.

A rendszer egyik lehetséges alkalmazása az elosztott objektumok. Ha az objektum másolatát nem frissíti a helyi ügyfelek, akkor a hálózaton keresztül szétszóródhatnak. Egészen más kérdés, hogy összehangolják a több példány frissítését. Olyan szabályt állíthat be, amely lehetővé teszi, hogy a példányszám csak olvasható legyen, de csak egy mester példány. Egy objektum frissítéséhez először meg kell szereznie egy master példányt a jelenlegi tulajdonosától. Persze, van, hogy figyelembe veszik a sok árnyalatok (különösen az eljárás megváltoztatása a tulajdonos a master copy), de a helyes alkalmazását vezető mutatók segítségével megvalósítani ezt a koncepciót meglepően egyszerű és átlátható, hogy az ügyfél.