terça-feira, 11 de dezembro de 2012

Programado en C++ / Klaso

Indekso

Klasoj

Estas du kategorioj de datumtipoj utila en C + + estas klasifikitaj kiel bazaj tipoj kaj tipoj difinita de la programisto.
Ĝuste kiel en C, oni povas difini datumoj engaĝante kombinaĵoj de la bazaj tipoj, tiuj tipoj estas nomitaj strukturoj (structs). C + + alportas novajn datumojn reprezento, tre simila en formo al la strukturoj, sed malsama en koncepto formo: la klaso ŝlosilvorto, kiu estas uzita por krei pli riĉan klaso de objektoj kiuj structs. Kiam vi deklaras ensalutilo, kiel kiam ni deklaras variablon en loko de tipo especifiquemos klaso kreos objekto.
Antaŭ ol ni daŭrigos, vidu iom sur la koncepto malantaŭ la uzo de celoj. Objekto estas komprenita kiel ento datumojn en memoro kiu esence devas esti respondeca por ilia enhavo, te, objekto devas povi memstare administri siaj enhavo, aŭ havigi aliaj rimedoj de kodo entoj fari ĝin tiel sekura.

Origino (atributoj)

Observi, ekzemple, jena kodo:
 struct MyData
 {Mez n;
   char datumoj [10];
   nReal kaleŝego;
 };
Tiu deklaro, bone konata al tiuj, kiuj estas jam familiaraj kun la lingvo C, kreas heterogena komponaĵo datumtipo, kiu en ĉi tiu ekzemplo nomis MyData, kio okazas ĉi tie estas, ke la datumoj estas kolektitaj ene de ĉi tiu kadro, ĝi promocias la eblon de manipulanta ilin kune. Unu problemo kun ĉi tiu strukturo estas la ĉeesto de tabelo de signoj nomita "datumo", note ke ĝi havas difinita longo de 10 signoj, imagu ke en iu punkto de la programo provis meti gravulo ĉe pozicio 11, aŭ iu pozicio ekster la mortas, en ĉi tiu kazo estas donitaj en meti diris nevalida adresoj al kiu ni plenumos la operacio, te ne estas kontrolo por certigi ke la kodo faros aliron ekster la areo apartenanta al la matrico. Al memoro aliro al ajna ero de la tabelo pli supre la 9 pozicio, kaŭzos invadamos datumoj en la areo kie la variablo estas metita nReal.

Membro funkcioj (metodoj)

Nun supozu ni starigis kiel maniero por eniri kaj alia por legi datumoj matrico:
 struct MyData
 {Mez n;
   char datumoj [10];
   nReal kaleŝego;
 
   write_data bool (int post, char c)
     {Se (post> = 0 && post <10) 
           {Datumoj [post] = c;
               revenu vera;
           }
       revenu falsa;
     }
 
  char read_data (int post)
     {Se (post> = 0 && post <10) 
           {Reiri datumoj [post];
           }
       revenu '\ 0';
     }
 };
Nun ni havas atingita metodoj de inkludo kaj aliro al la datumoj tabelo de signoj, sed estas ankoraŭ malgranda problemo: Kiu volas la malnova metodo de rekta aliro akiri facile ĉar la elementoj de estutura estas publike alirebla defaŭlte.

Koncepto

La problemo de publika videbleco de datumoj en strukturo povas esti solvita per unu el la konceptoj de celoj, encapsulación. Encapsular datumoj, signifas rezervante aliron al funkcioj kiuj estas ene de malgranda grupo, specialigita operacioj tia manipulado de datumoj. Unu avantaĝo de ĉi tiu proceduro estas, ke la kodo ricevas pli organizita formato, kie la procezoj fariĝis klare distingaj, se ni devas analizi la kodo, ĉiu proceduro estos limigitaj al partoj difinita por ĉiu operacio.

Deklarante klasoj

La strukturoj estas tre similaj al klasoj, kun malmulta diferenco, ni prenu la kazon de pasi strukturoj kiel funkcio argumentoj:
 # Inkluzivi <iostream>
 # Inkluzivi <string>
 # Ifndef Win32 / / En kazo ĝi ne estas programado en Vindozo
     # Inkluzivi <conio.h> / / estos inkluzivita en la biblioteko conio.h
 # Endif / / permesante uzo getch () anstataŭ sistemo ("paŭzo");
 
  uzante nomspaco std;
 
  klaso Persono 
  {
    kordoj nomo; 
    int alteco;
  };
 
  void setValues ​​(Person &);
  void getValues ​​(Person const &);
 
  int main ()
  {
    Persono p1;
    setValues ​​(p1);  
    cout << "Enirante datumoj sur la persono: \ n";
    cout << "================================ \ n";
    getValues ​​(p1);
 # Ifdef Win32
    sistemo ("paŭzo");
 # Else
    getch ();
 # Endif
    revenu 0;
  }
 
  void setValues ​​(Person & pers)
  {
    cout << "Tajpu la persono nomo:";
    getline (cin, pers. nomo);
    cout << "Tajpu la alteco en milimetroj:";
    cin >> pers. alteco; 
    cin. ignori ();
  }
 
  getValues ​​void (const Persono & pers)
  {
    cout << "Nomo de persono" << pers. nomo << endl; 
    cout << "La persono alteco en milimetroj estas:" << pers. alteco << endl;
  }

  • Ni ŝanĝis la struct ensalutilo por klaso
  • Sed se ni provos traduki la programo kaŭzos kompili erarojn, ĉar ni havas nun membro variabloj kiuj estas privataj implicite, tiuj ne estas vidita de funkcioj ekster la klaso.

Post unu klaso povas difini malsamajn modojn de videbleco de variabloj kaj funkcioj.
La proceduro povas esti:
  • privataj (nur povas konsenti por membroj de la sama klaso)
  • publika (povas aliri ekster la objekto kie estas metita)
  • protektitaj (forlasi tiun cxar kiam ni parolas pri derivaĵoj klasoj, ĉar dependas de tiu koncepto).
Tamen, kiel la funkcioj kaj getValues ​​setValues ​​ne estas membroj de la Persono klaso kiel la constructor Persono, ne povas aliri la variabloj "nomo" kaj "alteco".
Best imagis en tabular formo:
Klaso Persono privatajn

kordoj nomo

Int alteco
p1
La solvo estas krei publikaj funkcioj, legi de kaj skribi al la privata variabloj:
  # Inkluzivi <iostream>
  # Inkluzivi <string>
  uzante nomspaco std;
 
  klaso Persono 
    {
    privata:
       kordoj nomo; 
       int alteco;      
    publika:
       kordoj getName () const;
       void setName (linio);
       int getHeight () const;
       void setHeight (int);
    };
 
    Persono :: string getName () const
    {Reveno nomo;}
 
    void Persono :: setName (string j)
    { 
       if (s. length () == 0)
          nomo = "Neniu nomo atribuita";
       alie
          nomo = s; 
    }
 
    int Persono :: getHeight () const
    {Reveno alteco;}
 
    void Persono :: setHeight (int h)
    { 
       se (h <0)
          alteco = 0;
       alie
          alteco = h; 
    }
 
  void setValues ​​(Person &);
  void getValues ​​(Person const &);
 
  int main ()
  {
    Persono p1;
    setValues ​​(p1);  
    cout << "elirigi persono datumoj \ n";
    cout << "====================== \ n";
    getValues ​​(p1);
    revenu 0;
  }
 
  void setValues ​​(Person & pers)
  {
    string str;
    int h;
    cout << "Tajpu la nomo de persono:";
    getline (cin, str);
    pers. setName (str);
    cout << "Enter alteco en milimeters";
    cin >> h;
    cin. ignori ();
    pers. setHeight (h);
  }
 
  getValues ​​void (const Persono & pers)
  {
    cout << "Persono nomo:" << pers. getName () << endl; 
    cout << "Persono de alteco en milimeters estas:" << pers. getHeight () << endl;  
  }
Ili demandas: Kial ni donis la taskon uzi privatajn membroj anstataŭ fari ĉiu publika? Kiam ni havis strukturon en loko de klaso, estis nenio por malhelpi metante nevalida valoroj, do ni povus havi al malplena linio valoroj kaj negativajn valorojn por la variablo "alteco".
Nun ke "Persono" estas klaso membro funkciojn povas okupi datumoj validación antaux atribui valorojn al variabloj. Ni povus fari la setName funkcio por kontroli ĉu la enigo kordoj devus esti malplena kaj se ĝi estis, metis defaŭlta valoro kiel "anonima". simile oni povis havi "setHeight" por kontroli ke enigo valoroj lokus kaj se ili estis negativa, metis nulo, aŭ ne realigi agon.
Ĉiuj de ĉi tiuj karakterizaĵoj pruvi la koncepton de encapsulación. Lia celo estas fari la kodon pli modularized, restriktante la medio de analizo al partoj de klare difinita programoj. Pro tiu koncepto povas havi kodojn facile analizi kaj subteni.

Instantiating objektoj

Objekto instantiation estas la procezo de kreado la logika strukturo de la sama memoro. Tio okazas kiam ni deklaras la celojn, ĉar nun la tuta procezo de konstruo estas la sama efiko. Do, ĉiufoje kiam ni deklaras objekto instantiating ĝin, te, ni kreas petskribo de la klaso.
Ni povas deklari la celoj starigis baldaŭ post la klaso kiel povas vidiĝi en Kazo 1 sube. En ĉi tiu kazo ni kreis variablo kiel objekto rect kiel establita de la modelo difinita de la klaso ŝlosilvorto. Tiu tipo de frazo estas pli kutima por celoj kreis tutmonde, ĉar la inkludo de tiu deklaro en la kaplinio povas havi plurajn objektojn estas kreitaj kun la sama nomo kiel la kaplinio estas alvokebla multnombraj arkivoj. Sekve, estas pli singarde uzu tiun opcion kiam la propozicio estas en la fonto dosiero kaj ne en la kaploko.

1-a kazo:
  klaso CRectangle 
  {
    int x, y;
   publika:
     set_values ​​void (int, int);
     int areo (void);
   Rect};
En la 2-a kazo, prezentita pli sube, povas deklari celoj nur kiam ni bezonas ĝin. Ĉi tiu eblo de deklarante la objekto do estas la plej uzita ĉar plejofte ni havas la modelo de la celoj, la klaso deklaris en kapdosiero dum la objektoj estas kreita en la resto de la fontokodo. Tiel estas pli kutima por krei klasoj en titolaj kaj poste mi rakontos la objektoj en la programo kiu estas plej oportuna.

2-a kazo:
 klaso CRectangle 
  {
     int x, y;
   publika:
     set_values ​​void (int, int);
     int areo (void);
   };
 
  int main ()
  {
   CRectangle rect;
  }

En ambaŭ kazoj ni havas
CRectangle Privata publika

int x

int y


set_values ​​void (int, int);


int areo (void);
rect
Ni povas tiam kompreni la celojn kiel blokoj de datumoj, kiuj havas propraĵoj (variabloj) kaj ili povas fari ion (metodoj). Tiam ni kreas ĉiujn funkciojn ni bezonas havigi la klaso programoj, farante la necesajn provojn por certigi lian konsekvenco kaj establidade. Kiam ajn ni bezonas uzi la objektojn nur devas instantiate ili (deklari ilin), kaj ni ne bezonas zorgi kiel funkcias interne, ekde la egaleco konvene.
Por pli bone kompreni tiun koncepton povas fari analogion. Konsideri objekto rezisto: ni scias ke ni devas uzi ĝin kaj ŝi devas havi iujn trajtojn, tiam ni havi lian valoron en omoj, maksimuma povo, toleremo, inter aliaj, kaj havas funkcion kiu donos al ni la fluo kiu pasas tra ĝi kiam ni aplikas elektran tension. Ni ne bezonas scii kio estas farita, aŭ kiel tiuj internaj karakterizaĵoj faras funkcii, nur preni ni la rezultojn.
Prenu la ekzemplon:
Nun ni montras ke ni povas havi membron funkcioj nur kiel prototipoj kaj starigis ilin ekster klaso. CXar ni uzas la scoping operatoro :: kiu difinas la kodo situo kie estas identigilo en la formato: Medio :: Scope :: funkciodonita. Ĝenerale, kiam ni deklaras ensalutiloj ene de la klaso povas difini ilin en la tutmondan medion per referenco tiuj scoping operatoro.
  / / Ekzemplo klasoj
  # Inkluzivi <iostream>
  uzante nomspaco std;
 
  klaso CRectangle 
  {
     int x, y;
   publika:
     set_values ​​void (int, int);
     int areo () {return (x * y);}
  };
 
  CRectangle set_values ​​:: void (int a, int b) 
  {
   x = al;
   y = b;
  }                 
 
  / / Atentu la "::" kiu pemite ni difini la klaso membro funkcio ekster la klaso CRectangle
 
  int main () 
  {
   CRectangle rect / / difini klaso objekto
   rect. set_values ​​(3, 4) / / Membro objekto
   cout << "areo:" << rect. Areo ();
   sistemo ("paŭzo"); 
   revenu 0;
  }      
 
  / / Ekzemplo klasoj
  # Inkluzivi <iostream>
  uzante nomspaco std;
 
  klaso CRectangle 
  {
     int x, y;
   publika:
     set_values ​​void (int a, int b)
     {
      x = al;
      y = b;
     }
     int areo () {return (x * y);}
  };
 
  int main () 
  {
   CRectangle rect / / difini klaso objekto
   rect. set_values ​​(3, 4) / / Membro objekto
   cout << "areo:" << rect. Areo ();
   sistemo ("paŭzo"); 
   revenu 0;
  }
 Areo: 12
La antaŭa ekzemplo esploras karakteriza de ĉiuj fermitaj geometria figuro havanta internan areon. Notu ke ĉi maniero difini la klaso lokoj kalkuli la areo ene de la difino tio. Ĉi tiu modo kaŭzas la kodo esti nur unu modelo, la tasko de kalkulanta la areo ne estos kreita se ne uzita dum la skribo de la resto de la programo.

Preni alian ekzemplon:
  klaso Hundo 
  {
  publika:
     setAge void (int aĝo);
     getAge int ();
     setWeight void (int pezo);
     getWeight int ();
     neniigas paroli ();
  privata:
     int aĝo;
     int pezo;
  };
  void Hundo :: setAge (int aĝo)
  {
     ĉi -> aĝo = aĝo;
  }
  Hundo getAge :: int ()
  {
     revenu aktoj;
  }
  Hundo setWeight :: void (int pezo)
  {
     ĉi -> pezo = pezo;
  }
  Hundo getWeight :: int ()
  {
     revenu pezo;
  }
  void Hundo :: paroli ()
  {
     cout << "Bark" << endl;
  }
Super ni povas vidi metodon de deklarante funkcioj nur kiel prototipoj, kiuj estas ene de la klaso deklaro. En ĉi tiu kunteksto funkcioj estas difinita ekster la klaso, uzante la operatoro "::" por konekti la funkcion al la klaso. En ĉi tiu kazo ni difinis funkcioj kaj konstruita sur la sama kodo, dum la modelo de la klaso povas resti en header-dosiero, kiu permesas inkluzivi ĝin en ajna dosiero de fontkodo de la programo.

Difino de klasoj

Vi uzas la vorto "klaso" por krei klason, sekvis tiam la nomo kiun vi volas doni ĝin kaj fine opcio la sama krampoj.
La difino enhavas:
  • datumoj (propraĵoj);
  • metodoj (membro funkcioj)
Ni sekvos kun ekzemplo: Ni faru desegnon de klaso nomata "Dosiero", kiu estos uzita por stoki kaj manipuli bildon.
Unue demandu kion estas necesa por savi bildon, tiam kia manipuladoj bezonas.
La bildo estas 400 rastrumeroj larĝa kaj 300 rastrumeroj altaj. Ĉiu pixel havas la propraĵoj de koloro kaj bildo. La koloro komprenas ruĝa, blua kaj verda, sur skalo de 0 al 2 ^ {64} . Tial oni devas savi tiun informon por membroj
Nun ni planas metodoj. Unue, ni supozu, ke ni havas la limigon de <= 400 rastrumeroj, kaj tiujn valorojn estos farita de la konstruilo por krei la objekton. Ni ne bezonas metodojn por kondiĉas la alteco kaj larĝeco, sed ni bezonas por akiri kaj legi la valoroj. Tiu strategio ankaŭ helpos al ni subtenas la valorojn de donita pixel kaj lia loko.
La unua versio devus tiam esti:
  {Dosiero klaso
  publika:
     int getWidth ();
     int getHeight ();
     void setX (int x);
     int getX ();
     setY void (int y);
     getY int ();
     setRed void (duobla ruĝa);
     getRed duobla ();
     setBlue void (duobla blua);
     getBlue duobla ();
     setGreen void (duobla verda);
     getGreen duobla ();
  privata:
     int _width;
     int _height;
     int _x;
     int _y;
     duobla _red [400] [400];
     duobla _blue [400] [400];
     duobla _green [400] [400];
     isWithinSize bulea (int j);
     clipIntensity duobla (double brilo);
  };

Aliro Specifiers

  • Ni rezervis vortoj privata kaj publika - nomiĝas aliro specifiers.
    • privata - Indikas gamon de variabloj aŭ funkcioj kiuj povas aliri nur por membroj de la klaso, do neniu ekster la alia kodo povas aliri ilin;
    • publika - Indikas gamon de variabloj aŭ funkcioj kiuj povas aliri per iu kodo en la programo, kaj por la internaj funkcioj de la klaso ne necesas specifi la objekto dum por la aliaj partoj de la programo estas necese precizigi la celo al kiu ili apartenas .
Ĉi tiu funkcio por limigi aliron kaj manipuli membroj de klaso nomis encapsulación. Bona praktiko en la dezajno de klasoj devas ĉiam devigi la tunelo. Estas malofte necesa aŭ dezirinda havi liberan aliron al publika kaj internaj datumoj de klaso.
La pako celas unuavice du celojn:
  1. Forigi la bezonon por kono de la interna strukturo por tiuj, kiuj deziras uzi ĝin. Ekzemple, se la celoj devas subteni la aron de kvar bajtojn, tio povas esti atingita per uzo du variabloj mallongaj int, int unu, vektora kun kvar characteres, aŭ variado de iu el la antaŭa sensigna, sed ĉi tiuj detaloj estas ne bezonas esti elmontrita.
  2. Se la interna reprezentado de datoj estas modifita, kondiĉe ke la reveno tipoj kaj parametrojn de la publikaj funkcioj restas neŝanĝita, ni ne bezonas ŝanĝi kodo uzanta klaso celoj.
Tio estas, la encapsulación simpligas programado kaŝi particulariadades klaso kaj forigas adapti kodo por la sama ŝanĝo. Ĝenerale la funkcioj (metodoj) privata, estas helpaj al aliaj funkcioj de la klaso.
Se neniu aliro specifier uzas, ĉiuj membroj kaj metodoj estas deklaritaj privatajn defaŭlte.

Estas du metodoj por difini la membro funkcioj:
  • Ili povas esti difinita ene de la klaso, kiu estas taŭga por malgrandaj funkcioj;
  • Kaj ĉefaj funkcioj povas esti difinita ekster la klaso.
Ĉi tiu kazo devos esti identigitaj kiel apartenanta al tiu klaso kaj uzi la medio rezolucio operatoro "::".

Fabrikantoj

Koncepto

La konstruantoj "constructores" estas membro funkcioj (metodoj) de speciala klaso. Permesu inicialización de membro variabloj de objekto. Aŭ pli ĝuste, permesi la konstruon kaj inicialización de objekto klasoj. Se vi ne deklari la tradukilo faras ĝin por ni. La konstruantoj ĉiam havas la saman nomon kiel la klaso.
Objektoj estas konstruitaj tra tiuj specialaj funkcioj nomataj constructores. Ĝis nun ne deklari estis kreitaj aŭtomate. Ĉi tiuj funkcioj havas iujn karakterizaĵojn kiuj faras ilin malsamaj de normala, kiu ebligas al ili konstrui la logika strukturo de la originala objekto. Tiel tiuj funkcioj estas funkcioj de objekto orientiĝo kaj servi por krei ilin.
Constructores ne povas nomi eksplicite kiel ni faras en la kazo de funkcioj regula membro. Ili estas nur ekzekutita kiam nova objekto de la klaso estas kreita. Sekve, estas nur unu okazaĵo eblas ekzekuti constructor, la celo instantiation.
La ĉefaj karakterizaĵoj de la konstruistoj estas:
  • Ne havas ajnan tipon de reveno;
  • Ne povas esti interpretita de eksplicita alvoko en la kodo;
  • Kuru tuj post la baza tipo de objekto estis kreita;
  • Pravalorizi datumojn valoroj kiuj la objekto bezonas por komenci funkciadon konvene.

Deklaro

Ni povas facile krei constructores, tra la trajtoj kiuj distingas ilin de kutima membro funkcioj. Tio estas, ni difini funkcion membro kiu havas la saman nomon kiel la klaso, ne revenis tipo kaj deklari kiel publika do ĝi povas esti aliritaj ĉiu kiu volas instantiate celoj. Ni vidu kiel difini constructor:
 Plumo klaso
 {String koloro;
   int volumo;
   / / / / / / / / / / / / / / /
   publika:
     Plumo (string c, int v);
 };
 
 Plumo :: Plumo (string c, int v)
 {Koloro = c;
   v = volumo;
 }
Konstruistoj povas komenci klaso membroj en simpligita formo. Tiu formato estas uzata kiam la konstruisto havas bazajn datumojn kiuj povas komenciĝis antaŭ la resto de la konstruo de la strukturo de la objekto. Ni povas komenci la objekto datumoj deklarante ĝin tiamaniere:
 Plumo klaso
 {String koloro;
   int volumo;
   / / / / / / / / / / / / / / /
   publika:
     Plumo (string c, int v): koloro (c), volumo (v)
          {
          }
 };
Fari tiel, kiel ni vidas en la kodo, simple listigi la membro variabloj en vico post la deklaro de la fabrikanto nomon kaj dupunkto ":". Ni komencis liston de membroj, kun la kvanto esti atribuitaj en krampoj post ĉiu, disigitaj per komoj.

Destructors

Koncepto

Krom la konstruilo lingvo C + +, kaj aliaj objekteman lingvoj, havas malsaman tipon de papero speciale kreita kaj prizorgata de la lingvo, la destructors. Ĉi tiuj estas desegnita por malmunti la strukturo de la objekto kiam fermanta suben. The Detrua havas la saman nomon kiel la klaso, sed antaŭita de la signo supersigno "~" kaj ankaŭ revenas sen valoro.
The Detrua havas la sekvajn trajtojn:
  • The Detrua nomas kiam la objekto estas finita;
  • Ĝi estas uzata por liberigi ajna memoro kiu estis atribuitaj;

Deklaro

Lasu la Hundo klaso kun constructor kaj Detrua.
  klaso Hundo 
  {
  publika:
     Hundo () / / Constructor
     ~ Hundo () / / Detrua
     setAge void (int aĝo);
     getAge int ();
     setWeight void (int pezo);
     getWeight int ();
     neniigas paroli ();
  privata:
     int aĝo;
     int pezo;
  };
 
   Hundo Hundo :: ()            
  {
     aĝo = 0;
     pezo = 0;
     cout << "Constructor Called Hundo" << endl;
  }
 
  Hundo :: ~ Hundo ()
  {
     cout << "Detrua Called Hundo" << endl;
  }
Notu ke la
  • Constructor havas la saman nomon kiel la klaso;
  • The Detrua havas la saman nomon kiel la klaso kun la prefikso supersigno "~";
  • La konstruisto estis uzita por pravalorizi la membro variabloj, sed aliaj ekzemploj povus rezervi memoron rimedoj por proprigi aparatoj kaj realigi sistemon inicialización kodo;
  • The Detrua en la ekzemplo neniel reala ago, krom aserti ke la eĥo estis nomita.

"kopio constructores"

Al "kopio constructor" estas speciala konstruilo kiu prenas kiel argumento referenco al objekto de la sama klaso kaj kreas novan objekton kiu estas kopio de la objekto referenco. Defaŭlte, la tradukilo proponas "kopii constructor" kiu faras la membro de membro kopion de la originala objekto, konstrui identa objekto. Tiu nomiĝas "malprofunda kopio" aŭ "membro saĝa." En iuj situacioj kopion de objekto estas ne kontentiga por vidi ke ni vidos la oficisto klaso, sube:
  # Inkluzivi <iostream>
  uzante nomspaco std;
 
  klaso Oficisto 
  { 
    publika:
      Dependa (char * nomon, int id);
      ~ Oficisto ();
      char * getName () {reveno _name;}
    privata: / / Aliaj metodoj Accessor
      int _id;
      char * _name;
  };
 
  Oficisto :: Oficisto (char * nomon, int id)
  {
     _id = iru;
     _name = new char [strlen (nomo) + 1]; / / allocates tabelo objekto karaktero
     strcpy (_name, nomo);
  }
 
  Oficisto :: ~ Oficisto ()
  {
     forviŝi _name;
  }
 
  int main ()
  {
     Oficisto programisto ("John", 22);
     cout << programisto. getName () << endl;
     revenu 0;
  }
La strlen funkcio redonas la longecon de la kordo preteriris konstruilo. Rimarku ke la nomo de la oficisto nun stokitaj en karaktero tabelo dinamika. +1 Estas la kordo longitudo permesi nula Terminator stilo uzata en c.
La strcpy funkcio aŭtomate aldonas la nula Terminator string destino.
Ankaŭ rimarku ke la Detrua liberigas la memoro uzata por stoki la oficisto nomo, por eviti memoro fugo.
Nun imagu ke john estas promociita:
  int main ()
  {
     Oficisto programisto ("John", 22);
     cout << programisto. getName () << endl;
 
     / / Multaj kodo ....
 
     Oficisto direktisto (& programisto);
         / / Kreas novan Oficisto "direktisto"
         / / Kiu estas la ekzakta kopio de la
         / / Oficisto "programisto".
 
     revenu 0;
  }
Tiu programo enhavas seriozan cimo kaj mortas kun escepto kiam kuri. La problemo estas ke la konstruilo uzata por krei objekton "direktisto" sed kopias la adreson de la puntero en _name "direktisto".
Ni havas du punteros ambaŭ enhavas la sama adreso. Imagu nun ke nova oficisto dungita. kiam la nomo estas ĝisdatigita, ni ne nur ŝanĝi la nomon de la oficisto, sed ankaŭ la direktisto. Fine, kiam objektoj estas ne plu uzata kaj la Detrua de la klaso faras la liberigo de libera memoro spaco provu dufoje al la sama adreso, kaŭzante eraro en la sistemo de dinamika memoro atribuo, kio devigos la mastruma sistemo por forigi la programon la memoro.
Por solvi tiun problemon ni difini kopion konstruilo ("kopio constructor") en la klaso, anstataŭante la defaŭlta efektivigo de la tradukilo. Ĉi tiu funkcio estas aŭtomate identigita kaj kaŭzas la tradukilo ne kreas lian version de la konstruilo. Do, difini kopion konstruilo mem estas la plej efika maniero kiam nia celojn teni trajtojn kiuj faras ilin malsamaj de la defaŭlta.
Por krei la konstruanto simple difini ĝin en la klaso:
  # Inkluzivi <iostream>
  uzante nomspaco std;
 
  klaso Oficisto 
  { 
    publika:
      Dependa (const Oficisto & e);
      Dependa (char * nomon, int id);
      ~ Oficisto ();
      char * getName () {reveno _name;}
    privata: / / Aliaj metodoj Accessor
      int _id;
      char * _name;
  };
 
 Oficisto :: Oficisto (const Oficisto & e);
  {
     _id = e._id;
     _name = new char [strlen (e._name) + 1]; / / allocates tabelo objekto karaktero
     strcpy (_name, e._name);
  }
Nun ni havas konstruanto kiuj povas fari kopion ĝuste. En ĉi tiu nova konstruilo rezervu string kopii la enhavon de la originala objekto esti kopiitaj kaj kopii la enhavon al la nova objekto. Do ni havos malsamajn celojn, ĉiu kun sia enhavo.

Nenhum comentário:

Postar um comentário