Descriptorii din c

șablon

inline Tip * MP:: operator -> () const

Deci, după o mică încălzire, pointerii inteligenți s-au transformat în cei care conduc. Acum, în băutura noastră există încă un ingredient - mânere de C ++. Nu confunda acest termen cu descriptorii utilizați în sistemele de operare Macintosh și Windows. Există o anumită asemănare, dar idiomul descriptorilor C ++ are propria semantică unică și un set de reguli.







Ideea de bază este să folosiți pointeri inteligenți pentru a face referire la indicii de vârf. Acești indicatori suplimentari sunt numiți descriptori. Baza pe care vom construi clasa descriptorilor, în prima aproximare arata astfel:

șablon

MP operator -> () const

Constructorul non-argument H crează un nou indicator poștal. Acest pointer principal, la rândul său, creează obiectul specificat. Există un al doilea constructor care primește pointerul principal și inițializează variabila ptr. Constructorul de copiere și operatorul = sunt potrivite în mod implicit, deoarece pot exista mai multe descriptori pentru orice indicator poștal. Operatorul -> operație se bazează pe algoritmul recursiv utilizat de compilator: operatorul descriptor -> returnează indicatorul principal; atunci operatorul -> leader pointer returnează un pointer de tip * care este unul dintre tipurile de bază ale compilatorului.

Soluția de mai sus nu poate fi numită modele elegante - imbricate care creează confuzie și este complet neclar când și cum să eliminați indicii de vârf. De asemenea, ar trebui să permiteți utilizatorului să creeze și să distrugă în mod direct indici de frunte sau să le închidă în descriptori așa cum încapsulăm obiectele specificate în interiorul indicilor de vârf? Ne-am străduit să rezolvăm aceste probleme doar pentru obiecte ascuțite și apoi să le confruntăm din nou pentru indicatori de vârf? Răbdarea - în timp util vom găsi răspunsul la aceste și multe alte întrebări.

Ce se întâmplă?

Vom începe cu un exemplu simplu de indicatori de vârf și îl vom îmbunătăți până la un nivel care să satisfacă chiar și publicul mai solicitant. În acest stadiu este încă dificil să înțelegem beneficiile complete ale descriptorilor, dar în următoarele capitole acestea vor juca un rol foarte important.

Numără obiecte

Să presupunem că doriți să urmăriți numărul de obiecte dintr-o clasă care au fost create sau sunt în memorie. O posibilă soluție este aceea de a stoca această informație în variabilele statice ale clasei.

clasă CountedStuff

static curent int; publice:

CountedStuff () Conținut (const CuntedStuff) CountedStuff operator = (const CountedStuff)







<> // Nu modificați contorul de sarcini

Cu acest exemplu, puteți continua să-l îmbunătățiți și să-l îmbunătățiți, dar indiferent cât de greu încercați, va trebui să schimbați codul clasei țintă - cel puțin pentru a-l moșteni de la clasa noastră. Acum presupuneți că obiectul specificat intră în biblioteca comercială. Este o rușine, nu? Orice schimbări sunt nedorite, dar cel mai probabil, pur și simplu imposibile. Dar aici vine clasa indicelui principal.

șablon clasa CMP

static curent int; Tip * ptr;

CMP (const CMP cmp). ptr (nou tip (* (mp.t))) CMP operator = (const CMP cmp)

dacă (acest! cmp)

ptr = nou Tip (* (cmp.ptr));

Acum, indicatorul de plumb efectuează toate calculele pentru dvs. Nu necesită modificări ale clasei obiectului specificat. Acest model poate fi folosit pentru orice clasă, cu condiția ca va fi capabil de a stoarce mai multe indicii între client și specificați obiectul. Chiar dacă nu te deranjează o modificare a clasei inițiale a obiectului desemnat, să asigure un nivel de modularitate, fără indicatori de conducere ar fi extrem de dificil (de exemplu, dacă ați încercat să lucreze prin intermediul clasei de bază, rezultatul ar avea un curent variabilă statică pe toate clasele derivate).

Acest exemplu este trivial, dar chiar demonstrează un principiu important al programării în C ++, valabilitatea căreia devine evidentă în timp: folosiți pointeri inteligenți, chiar dacă la început se pare că nu sunt necesari. Dacă programul este scris pentru indicații inteligente, toate modificările se fac ușor și rapid. Dacă trebuie să refaceți programul finit și să înlocuiți toți operatorii cu indicatori inteligenți, pregătiți-vă pentru vigilențele de noapte.

În capitolul 14, variațiile subiectului de numărare vor fi folosite pentru a implementa o schemă simplă, dar puternică de gestionare a memoriei, colectare de gunoi cu numărare de referință.

Numerele de citire numai

Să presupunem că doriți să vă asigurați că un obiect nu este niciodată actualizat (sau cel puțin nu este actualizat de clienți obișnuiți). Această problemă este ușor de rezolvat cu ajutorul unor indicatori de vârf

- este suficient ca operatorul -> () să ocupe funcția constantă a clasei.

șablon

ROMP operator = (const ROMP); const Tip * operator -> () const;

Obiectul specificat este blocat atât de fiabil încât nici CIA nu va ajunge la el. În principiu, același lucru se poate face și cu indicatori simpli mai inteligenți, dar indicatorii de vârf oferă o protecție de 100%, deoarece clientul nu obține niciodată acces direct la obiectul specificat.

Indicator pentru citire / scriere

În multe situații, există o reprezentare optimă a obiectului, care este valabilă numai pentru operațiile de citire. Dacă clientul dorește să schimbe obiectul, vizualizarea trebuie schimbată.

Acest lucru ar fi ușor de făcut dacă există două versiuni supraîncărcate ale operatorului ->. dintre care unul returnează Foo *. iar celălalt este const Foo *. Din păcate, diferitele tipuri de întoarcere nu oferă unicitatea semnăturilor, deci atunci când încercați să declarați doi operatori -> compilatorul va râde cu inima. Programatorul va trebui să sune în prealabil o funcție care efectuează trecerea de la o prezentare la alta.

Una dintre posibilele aplicații ale acestei scheme este distribuirea obiectelor. Dacă copii ale obiectului nu sunt actualizate de clienții locali, ele pot fi împrăștiate în întreaga rețea. Este o altă chestiune de a coordona actualizările mai multor instanțe. Puteți stabili o regulă care să permită ca orice număr de copii să fie citit, dar numai o singură copie de bază. Pentru a actualiza un obiect, trebuie mai întâi să obțineți o copie de bază de la proprietarul actual. Desigur, trebuie să luăm în considerare multe nuanțe (în special, procedura de schimbare a proprietarului copiei de master), dar aplicarea corectă a indicatorilor de conducere permite realizarea acestui concept este surprinzător de simplu și transparent pentru client.







Trimiteți-le prietenilor: