Moștenirea într-o limbă cu

modificatori moștenire

Suntem în sfârșit gata să vorbească despre moștenire. Aceasta este una dintre cele mai interesante calități ale limbajului C ++. Moștenire in C ++ - un mecanism prin care o clasă poate moșteni caracteristicile altui. Moștenirea vă permite să construiască o ierarhie de clase, trecând de la mai general, la mai specifice.

Atunci când o clasă este moștenită de o altă clasă care moștenește, a numit-o clasă derivată. clasa Moștenind se numește clasa de bază.

Noua clasă se bazează pe structura existentă folosind formularul de mai jos:

Părinte clasă;
clasa Child. [Modificator moștenire] Părinte;

La determinarea descendenților clasă pentru numele lui să fie separatorul, două puncte (:), și apoi - o moștenire modificator opțional, numele clasei părinte. modificator Moștenirea determină vizibilitatea variabilelor moștenite și metode de utilizator și posibile descendenții clasei descendent. Cu alte cuvinte, aceasta determină ce drepturi de acces la variabile și metode ale părintelui de clasă va fi „delegată“ la clasa-descendent. La punerea în aplicare moștenire, zona de „vizibilitate“, a datelor care aparțin clasei și metodele pot determina alegerea cuvintelor cheie privat (private), publice (public) sau protejat (protejat), care se poate roti liber, într-o clasă. Cu primele două modificatorii de acces suntem deja familiarizați, - privat închis descrie membrii clasei la care accesul metode sunt numai membrii acestei clase, publicul este folosit pentru a descrie elementele publice, care pot fi accesate de oriunde în program. De un interes deosebit sunt elementele care au acces protejat modificator. modificator protejat este utilizat atunci când este necesar ca unii membri ai clasei de bază rămân private, dar ar fi disponibile pentru clasa derivată. Protejat echivalent privat, cu o singură excepție: membrii clasei de baza protejate sunt accesibile membrilor tuturor claselor derivate din clasa de bază.

Acesta este modul în care elementele de acces ale clasei de baza a clasei derivate de metode, în funcție de modificatori de moștenire valoare este dată în tabel.

Din tabelul de mai sus arată, într-un acces de clasă derivată la elementele clasei de bază pot fi făcute mai limitate, dar niciodată nu se poate face mai puțin limitată.

Constructori și destructori atunci când moștenirea

Clasa de bază, o clasă derivată, sau ambele pot avea un constructor și / sau destructor.

Dacă la bază și clase derivate au constructori si destructori, constructorii sunt executate în ordinea succesiunii și destructori - în ordine inversă. Ie dacă A este clasa de baza B - derivată din A și C - este derivat din B (A-B-C), atunci când un obiect de designeri provocare clasa C va avea următoarea procedură: A Designer - constructor B - C. apel constructor la destructori distrugerea obiectului va avea loc în ordine inversă: destructor - destructorul - destructor A.

Înțelege modelul unui astfel de ordin nu este dificil, deoarece clasa de bază nu „știe“ despre existența clasei derivate, orice initializare se face în ea, indiferent de clasa derivată, și poate deveni baza pentru initializarea efectuate într-o clasă derivată. Pe de altă parte, deoarece clasa de bază stă la baza derivatului destructor clasă de bază apel înainte de destructor clasă derivată ar conduce la defectarea prematură a clasei derivate.

Acest program afișează următoarele

Activitatea constructorului clasei de baza
derivat munca constructorului clasei
Lucrări derivate destructor clasa
destructor de lucru din clasa de bază

Am vorbit deja despre faptul că designerii pot avea parametri. La punerea în aplicare de succesiune a permis parametrii de transmisie pentru constructori și un derivat al clasei de bază. Dacă parametrul are doar argumente derivate din clasa constructor care sunt transmise într-un mod convențional. Cu toate acestea, dacă este necesar, să treacă un argument pentru constructorul clasei parinte, este nevoie de ceva mai mult efort. În primul rând, trebuie să aibă grijă de asta pentru a trece de la clasa de constructorul clasei de baza constructor derivate. În acest scop, a extins recordul constructorului clasei derivate.

konstruktor_proizvodnogo_klassa (lista oficială de parametri)
. konstruktor_bazovogo_klassa (lista reale ale parametrului)
. // corp constructor clasa derivata
>

posibil să se utilizeze aceleași setări pentru bază și clasele derivate. Este posibil, și că listele constructorilor parametrii derivati ​​și clasele de bază vor fi diferite. Mai mult, constructorul clasei derivate nu este necesar să se utilizeze toate argumentele primite pentru transmiterea la clasa de bază, și anume constructorul clasei derivate poate accepta unele dintre argumentele doar pur și simplu le trece la constructorul clasei de bază, și poate că nu le folosesc.

BaseClass clasa
int i;
publice:
BaseClass (int ii)

DerivedClass clasă: BaseClass publice
int n;
publice:
DerivedClass (int nn, int m): BaseClass (m)

De asemenea, este posibil ca constructorului clasei de bază poate avea mai multe opțiuni decât constructorul clasei derivate.

BaseClass clasa
int j, i;
publice:
BaseClass (int jj, int ii)

DerivedClass clasă: BaseClass publice
int n;
publice:
DerivedClass (int nn);

DerivedClass. DerivedClass (int nn): BaseClass (nn / 2, nn% 2)

EXEMPLU construirea clase și moștenire

Ca un exemplu, alege grafica, utilizarea care poate fi util în diferite domenii. Este rezonabil să se înceapă cu o clasă care simulează construirea de pixeli fizice de pe ecran.

Dar pixelii de pe ecran, în plus față de coordonatele poziției sale, de asemenea, are capacitatea de a „aprinde“. Extindeți structura:

enum Boolean; // false = 0, true = 1
struct Punct
int X;
int Y;
Boolean vizibil;
>;

tipul boolean este familiar programatorilor Pascal. Acest cod utilizează tipul de enumerare enum pentru a verifica adevărat (true) sau fals (false). Deoarece valorile de tip enumerare încep de la 0, atunci Boolean poate avea una dintre cele două valori: 0 sau 1 (adevărat sau fals).

Având în vedere experiența noastră cu _3d structura, trebuie să aibă grijă de interfață de clasa Point. Vom avea nevoie de metode pentru inițializarea coordonatele pixelilor și instrucțiunile „pe“ sau nu. În plus, dacă dorim să ne asigurăm variabila internă nu este disponibilă, ar trebui să ofere o modalitate de a afla ce este în ele, citește valorile lor reglementate mod. Următoarea versiune ar putea arata ca:

enum Boolean; // false = 0, true = 1
Punctul de clasă
<
protejate:
int X;
int Y;
Boolean vizibil;
publice:
int GetX (void)
int gety (void)
Boolean isVisible ()
Punctul (punctul Const cp); // constructor de copiere prototip
Litera (int newX = 0, int nou Y = 0); // prototip constructor
>;

Punct. Punctul (int NewX, int NewY) // Constructor
X = newX; Y = newY; Vizibil = false;
>

Punct. Punctul (punctul Const cp) // constructor de copiere
X = cp.X; Y = cp.Y; Vizibil = cp.Visible;
>

Acum avem posibilitatea de a declara obiecte de tip punct:

Punctul Center (320, 120); // obiect de tip Punct Centru
Punctul * point_ptr; // pointer la punctul de tip
point_ptr = &Center; // indicatorul să Centrul

Setarea argumentelor implicite atunci când descrie prototipul constructorului ne permite de a apela constructorul fără argumente sau cu o listă incompletă de argumente:

Punctul Apoint ();
Punctul Row [80]; // array de obiecte de tip punct
Punctul bPoint (100);

Atâta timp cât putem crea obiecte de clasa Punct și de a determina locația lor, dar nu le putem arăta încă. Deci, aceasta trebuie să fie completată prin metode adecvate punct de clasă.

Punctul de clasă
.
publice:
.
void Show ();
void Hide ();
void MoveTo (int newX, int newY);
>;

void :: Punctul Show ()
Vizibil = true;
putpixel (X, Y, getcolor ());
>

void Punct :: Ascunde ()
Vizibil = false;
putpixel (X, Y, getbkcolor ());
>

void Punct :: MoveTo (int newX, int newY)
Hide ();
X = newX;
Y = newY;
Show ();
>

Acum, că avem un punct de clasă completă, puteți crea point-obiecte, evidențiați, călire și mutați-le pe ecran.

Punctul pointA (50,50);
pointA.Show ();
pointA.MoveTo (100,130);
pointA.Hide ();

Dacă trebuie să creați o clasă pentru un alt grafic, atunci unul din cele două moduri, puteți alege fie să înceapă punerea sa în aplicare „de la zero“, sau de a folosi gata făcute punct de clasă, făcându-l de bază. A doua cale pare a fi de preferat, deoarece implică utilizarea de module gata făcute, toate în același timp, aveți nevoie - este de a crea o nouă clasă derivată de la Point, completarea cu noi condiții și metode și / sau redefinirea unora dintre metodele clasei de bază.

Să încercăm să creeze o clasă pentru cerc cerc. Un cerc într-un sens, un punct de grăsime. Ea are tot ceea ce are un punct (poziția X și Y și starea vizibil / invizibil), plus raza. Aparent, clasa Circle pare să aibă doar un singur element al Radius, dar nu uita cu privire la toate elementele care moștenește Circle, fiind clasa generată de punctul. Cercul are X, Y, și vizibile, chiar dacă acestea nu sunt vizibile în definiția de clasă pentru cercul.

Clasa de cerc: Punct publice
int Raza; // private în mod prestabilit
publice:
Circle (int initX, int initY, int initR);
void Show ();
void Hide ();
void Expand (int deltaR);
void Contract (int deltaR);
void MoveTo (int newX, int newY);
>;

Circle :: Circle (int initX, int initY, int initR) // Constructor
: Punctul (initX, initY) // apelează constructorul clasei de baza
Raza = initR;
>

void Circle :: Show ()
Vizibil = true;
cerc (X, Y, Radius);
>

void Circle :: Hide () // ascunde culoarea de fundal schiță =
Vizibil = false;
unsigned int tempColor = getcolor ();
setcolor (getbkcolor ());
cerc (X, Y, Radius);
setcolor (tempColor);
>

void Circle :: Expand (int deltaR)
Hide ();
Raza + = deltaR;
Show ();
>

void Circle :: Contract (int deltaR)
Expand (-deltaR);
>

void Circle :: MoveTo (int newX, int newY)
Hide ();
X = newX;
Y = newY;
Show ();
>

main ()
int graphDr = DETECT, graphMode;
initgraph ( graphDr, graphMode, "");

Circle C (150,200,50); // crea un obiect al unui cerc centrat la r. (150, 200) și raza de 50
C.Show (); // arată cercul
getch ();
C.MoveTo (300,100); // mutare
getch ();
C.Expand (50); // întindere
getch ();
C.Contract (70); // stoarce
getch ();

Deoarece Cercul clasei - este derivată din clasa de punct, respectiv, clasa Circle moștenește de la punctul X stare de clasă, Y, vizibile și metode isVisible (), GetX (), gety (). În ceea ce privește metodele de Show (), Hide () și MoveTo () clasa Circle, necesitatea de a trece peste ele dictate de specificul unei noi clase de obiecte, ca, de exemplu, arată un cerc - nu este același cu cel prezentat prin puncte.

Observați că metodele de cerc necesită acces la diferite elemente de date din clasele de cerc și punct. Luați în considerare Cercul :: Expand. Este nevoie de acces la Radius. Nici o problemă. Raza este definit ca un privat în cerc. Prin urmare, Raza disponibilă pentru elementele funcționale ale clasei Circle.

Acum ia în considerare Circle :: Hide and Circle :: Show. Ei au nevoie de acces la Vizibilă din punctul său de clasă de bază. În acest exemplu, Vizibil a protejat Access Point. Un cerc este generat de la punctul de acces public. Prin urmare, Vizibil a protejat accesul în interiorul cercului. Rețineți că, dacă este vizibilă definită ca fiind private în Point, ar fi disponibile pentru funcțiile de elemente Circle. Ar fi posibil să se facă vizibil publice de acces c. Cu toate acestea, în acest caz, Vizibil ar pune la dispoziție funcții care nu sunt elemente.

compatibilitate tip

Moștenind cererile sale de a regulilor de tipuri de compatibilitate.

În plus față de orice altceva, tip generat moștenește compatibilitatea cu toate tipurile de celule progenitoare. Această compatibilitate extinsă are trei forme:

  • între instanțe de obiecte,
  • pointeri între obiecte,
  • între parametrii formali și cele reale.

Cu toate acestea, în toate cele trei forme pe care trebuie să ne amintim că tipurile de compatibilitate se extinde de la copil la părinte. Cu alte cuvinte, clasele generate pot fi utilizate în mod liber în locul claselor strămoș, dar nu și invers.

Punctul Apoint, * ptrPoint;
Cercul ACircle, * ptrCircle;

Atribuirea înapoi este ilegală.

Obiect părinte poate fi atribuit unui obiect din orice clasă generate de acestea.

Pentru a face mai ușor de reținut modul în care compatibilitatea tipurilor, hai să vorbim în acest fel:

1. Sursa trebuie să umple complet destinația obiectului,
2. Tipurile generate conțin toate tipurile conțin parentale prin moștenire. În consecință, tipul generat va avea sau aceeași dimensiune, sau (de obicei) mai mare decât predecesorul său, dar niciodată mai mică.

Atribuirea unui obiect părinte generat poate lăsa unele câmpuri descendent incert după atribuirea. Ceea ce este foarte periculos.

Ofertele de atribuire pentru a copia numai acele domenii care sunt comune pentru ambele tipuri, și anume câmp numai în strămoș.

tipuri de compatibilitate sunt de asemenea valabile între indicii pentru clase. Trimiteri către descendenții pot atribui indicii la strămoșii aceleași reguli generale ca și în cazurile de obiect.

Parametrul formal al unei clase de obiect poate fi folosit ca un obiect parametru real al aceleiași clase sau orice clasă derivată. De exemplu,

void Proc (punctul param)

Apoi, parametrii reale pot fi de tip punct, cerc și orice alt tip de generate de acestea.

Știați că o clasă abstractă - o clasă care conține cel puțin o metodă virtuală. clase abstracte nu sunt izolate, adică, întotdeauna o clasă abstractă trebuie să fie moștenită. Deoarece metoda virtuală pură nu este corpul, puteți crea un obiect de clasă abstractă nu poate fi. O clasă abstractă poate fi numită clasă definită în mod specific pentru caracteristicile de moștenire generate de clase.

Știri
Cavalerii Teoria eter