clasele C, propascal - toate pentru programatori

clasele C ++

Ce este cpp

Dintre toate limbile care susțin metodologia de programare orientate-obiect, C ++, poate că oferă cea mai mare oportunitate și cea mai mare flexibilitate pentru a gestiona crearea de clase și obiecte, accesul la membrii claselor, managementul memoriei, alocă obiecte. Cu toate acestea, nimic nu se întâmplă liber, iar puterea și flexibilitatea în limbajul C ++ trebuie plătit și complexitatea neevidenta a multora dintre proiectele sale.







Descrierea Sintaxa clasei

BazovyeKlassy este o listă de nume ale claselor de bază care indică accesul specificatorilor la clasele de bază. În cazul în care clasa nu are clase de bază, această listă nu se poate scrie (și nu pune preludiu la colon).

Iar în clasa membri ai definiției de clasă pot fi anunțate doar, dar va fi descrisă mai târziu. De exemplu:

Important! Anunțate (dar care nu sunt încă definite) clase pot fi utilizate numai în cazul în care nu este necesar să se cunoască cantitatea de memorie alocată de obiectul de clasă - adică, utilizarea autorizată, dar nu și numele anumitor clase este permisă numai indicii și descrieri referințe:

(Privind în perspectivă: problema pare doar exagerată în clasa GroupX (implicit), definit de către proiectant, care va avea nevoie pentru a crea obiectele de clasă Postul, nimic despre ei fără să știe.).

Această problemă nu apare în alte limbaje de programare (cum ar fi Delphi, Java sau C #), în care accesul la obiect clasa merge doar indicii chereh. Cu toate acestea, în C ++ obiect de clasă este considerată ca (secvență de biți) de date, mai degrabă decât ca un pointer la date.

Dreptul de acces la metode și domenii ale clasei

În C ++, există trei niveluri de drepturi de acces la membrii clasei.

Membrii clasei sunt declarate în secțiunile publice, accesibil de oriunde în program.

Membrii clasei sunt declarate în secțiunile protejate, accesibile numai clasei în sine (și metodele), precum și în clasele derivate de la el.

Domenii și metode sunt declarate ca fiind private, sunt disponibile doar într-o clasă (și metodele), precum și cursuri de „prietenoase“. Acest nivel de acces se aplică tuturor membrilor clasei la care drepturile de acces nu sunt specificate în mod explicit.

De multe ori există o situație în care mai multe clase diferite sunt strâns legate între ele. De exemplu, în cazul în care biblioteca de clasă este creat pentru a lucra cu algebra vector, inclusiv clasele Matrix si Vector, nu este fezabil din greu pentru a separa aceste clase, este foarte durabil, ele sunt legate. Și dacă da clasa Matrix poate avea acces numai membrii publice a vectorului de clasă, operațiunea dintre matrice și vectori vor fi dificil de implementat cu eficiența necesară. În cazul în care a făcut publică o reprezentare internă a vectorului, atunci va pierde această calitate importantă a unui model orientat-obiect detalii privind implementarea încapsulare într-o clasă.

Pentru a permite accesul la reprezentarea internă a clasei numai la unele alte clase, interzicând astfel un astfel de acces tot drumul, conceptul de „clasă prietenoasă“ a fost introdus în C ++. Clasa, acest ușor de utilizat, are acces la toți membrii săi, inclusiv cele declarate ca fiind private.

Constructorul inițializarea obiectelor acestei clase (adică inițializarea și nu crearea obiectului poate fi plasat nu numai în memorie alocată dinamic, ci și pe stivă (ca variabilă locală a unei funcții).

constructori Feature C ++, care sunt numite atunci când obiectul nu este creat până la sfârșitul anului. Prin urmare, există limite la apelul de la proiectant la alte metode de clasă (în special pentru metodele virtuale).

Sintaxa descrieri de designer

Constructorul în C ++ are același nume ca și numele clasei, și pot avea parametri (sau nu le au):

Există doi constructori sunt descrise: unul fără parametri (și va fi folosit ca constructorul implicit), iar cealaltă - cu un singur parametru de tip șir.

Și acum a crea obiecte:
C x; // constructorul implicit se numește
// este afișată // n = 0 C y =
«Abc»; // constructorul este apelat cu un parametru șir de caractere
// este afișată // n = 3 C z ( «abc»); // în cazul precedent
// este afișată // n = 3 C * p =
new C (); // obiectul este creat în alocarea dinamică a memoriei
// va fi afișată // n = 0 C * p =
new C ( «ABCD»); // un alt generat dinamic
obiect
// este afișată // n = 4

Aceasta este, constructorul se numește:
• atunci când creați în mod explicit un obiect într-o memorie alocată dinamic utilizând nou operator;
• Când inițializează variabilele descrise și membrii clasei;
• Când copiați obiecte (dar mai multe despre asta mai jos).

Un tip important de constructor este așa-numita „constructorul copy“. Constructorul de copiere este considerat a fi un constructor cu un singur parametru (sau cu prima opțiune, în cazul în care alți parametri au valori implicite) sunt:
• referire la const obiectul clasei;
• referire la obiectul clasei;
• instabil (volatile) sau constantă de referință instabilă referință la obiectul clasei.

Constructorul de copiere se numește:






• Inițializarea creat de un alt obiect obiect de aceeași clasă;
• transferul parametrului (nu un pointer!) Pentru funcția;
• La returnarea valoarea (nu indicatorul!) A funcției;
• La copierea unui obiect de atribuire (dar numai în cazul în care clasa nu a fost înlocuită de atribuirea operatorului!).

Constructorul de copiere și de atribuire

Posibilitatea de C ++ definit ca un constructor copy si operator de atribuire pentru a înlocui clasa necesită deosebit de atent cu privire la utilizarea operatorului de atribuire în astfel de cazuri, pentru că trebuie să știți exact ce se va numi: constructorul de copiere și operatorul de atribuire. De exemplu:

>;
Și acum toată această utilizare:
A a1; // numit A () pentru a inițializa constructorului
o
A a2 (a1);
// constructor copy este numit
A a3 = a2;
// constructor copy este numit din nou
B b;
A a4 (b);
// constructor este numit A (const B), // deoarece variabila
// obiect este inițializat cu o clasă B
A a5 = b;
// constructor este numit A (const B)
a1 = a5;
// numit operator de atribuire reimplemented
a2 = b;
// Ei bine, aici - o vacanță completă:
// - obiectul b creează un obiect temporar de clasa A
// constructor folosind A (const B)
// - reimplemented folosind operatorul de atribuire,
// atribuie a2 variabilă temporară creată instalația

Destructor este declarată în C ++ după cum urmează:

ClassName ();
Scopul său - să se pregătească obiect pentru eliminare. De exemplu, eliberarea resurselor obiectelor capturate.

Destructor este numit chiar înainte de eliberarea memoriei alocate pentru obiect:
• atunci când ștergeți în mod explicit un obiect, plasat în grămadă, folosind operatorul delete;
• la ieșirea variabilei a cărei valoare este obiectul (numele obiectului, nu un pointer la un obiect!) Afara domeniului de aplicare.

Distrugător pot fi declarate virtuale și supracomandată într-o clasă derivată.

Acest cuvânt cheie

Cuvântul cheie this oferă acces la metodele din clasa la un pointer la obiectul de clasă în sine. acest lucru este:
• indice de nume (indiferent de modul în care a fost creat obiectul);
• indicatorul const, adică, metode de clasă nu se poate schimba valoarea.

Prioritari operatori noi și ștergeți

Noul operator este folosit pentru a crea obiecte în memoria alocata dinamic, iar operatorul delete este utilizat pentru a elimina create anterior obiectele de memorie alocate dinamic. C ++ permite programatorului de a trece peste acești operatori, creând astfel un mecanism de gestionare a memoriei.

Înlocuirile noul operator trebuie să fie primul parametru de tip size_t (tipul utilizat în C ++ pentru a specifica dimensiunea memoriei, și, de fapt, este un număr întreg) și returnează un void * (adică, un indicator netipizat) este un pointer la memoria alocată pentru obiect .

Înlocuiri șterge operatorul trebuie să aibă un parametru de tip void *, indicând memoria ocupat de obiectul amovibil.

Iar operatorul nou, operatorul și ștergeți sunt metode statice, și, prin urmare, nu au capacitatea de a accesa datele create sau șterse obiect. (Cu toate acestea, deoarece void * pointer poate fi convertit la un pointer la obiectul de clasă, programator poate ajunge la datele obiectului, dar nu să facă acest lucru. - Sunt constructori și destructori pentru manipularea datelor pentru a crea și de a șterge obiecte).

Moștenirea vă permite să definiți o clasă derivată ca o extensie a clasei de bază. În plus, toți membrii clasei de bază există în clasa derivată. Dar nu toate dintre ele sunt disponibile ca reguli de acces la locul de muncă.

Din nou, spre deosebire de alte limbaje orientate obiect (Java, Delphi, C #), C ++ nu este comună tuturor claselor de clasa de bază. Fiecare clasă care nu este specificată clase de bază este unul dintre (posibil mai multe) noduri ierarhie de clasă.

C ++ - una dintre puținele limbi care permit moștenire multiplă, adică, clasa poate avea mai multe clase de bază. În acest descendent clasă vor primi toți membrii clasei sale de bază. descriere foarte simplificată a clasei
struct D: B1, B2
int n;
>

Se poate observa ca
struct D
__b1 B1;
__b2 B2;
int n;
>
În acest caz, pentru a avea acces la B1 și membrii B2 nu trebuie să specifice în plus „numele câmpurilor» __b1, __b2 și acces la numele lor direct din clasa obiectului D. Cu toate acestea (așa cum se obișnuiește în C ++), există unele nuanțe, care vor fi discutate mai jos .

Acesta este un instrument foarte puternic, care, în multe cazuri, este firesc să descrie structura de date fără a introduce concepte suplimentare (cum ar fi în Java «interfețe», Delphi sau C #). Dar, (ca și pentru alte C ++ modele puternice) pentru aceste posibilități bogate de a plăti complexitate crescută. De exemplu:

În C ++, există (și destul de complicate), norme care să permită majoritatea unor astfel de coliziuni. Dar, în multe cazuri, este mai bine să se precizeze în mod explicit ceea ce este în joc, folosind prefixe de spațiu de nume:

moștenire multiplă, și acest lucru

Atenție! Datorită posibilității de moștenire multiplă, această valoare pointer în obiectul de clasă derivată poate fi diferită de aceste valori pointer în obiectul clasei de bază (în special în cazul în care clasa de bază nu a fost primul din lista de clasa de baza)!

clase abstracte și funcții virtuale pure

Clasa care conține cel puțin o funcție pur virtuală este numită „clasă abstractă.“ clasa de obiecte abstracte nu pot fi create (inclusiv clasa abstractă nu se poate descrie variabilele, deși este posibil să se descrie un pointer la clasa de obiecte abstracte - valorile lor pot fi indicii pentru clase de obiecte descendent.

moștenire simplă și virtuală

Să presupunem că există o astfel de ierarhie de clasă:
clasa A
publice:
int n;
void f ();
>
clasa B1: A publică
>
clasa B2: Un public
>
și clasa C, care derivă din și B1, și de la B2.

Clasa C este un copil de clasa A și clasa B1 prin intermediul și prin clasă B2. În consecință, și cuprinde un n câmp, și metoda f (). În acest caz, există o ambiguitate: ce mod (prin B1 sau prin B2), există o referință la câmpul n și metoda f () din clasa C? Și, în general, cât de multe domenii n este un obiect de clasa C? Numai unul? Sau un câmp la B1 :: n și una pentru B2 :: n? Și dacă și metoda f () este suprascrisă într-una din clasele B1 sau B2 (chiar și în ambele clase)? O indicație clară a numelui de clasă atunci când se referă la metoda nu rezolvă problema.

Prin urmare, în C ++ a fost introdusă posibilitatea de moștenire virtuale: câmpuri și metode în declarația de clasă pentru a specifica că moștenește clasa de bază virtuală, atunci moștenite vor fi partajate cu alți moștenitori clasa de baza virtuale. În caz contrar, orice clasă va avea propriul set de câmpuri și metode moștenite. De exemplu:
clasa A
publice:
int n;
void f ();
>
clasa B1: virtual public A
>
clasa B2: virtual public A
>
clasa C: B1 publică, B2 publică
>

În acest caz, B1 și B2 clase, moștenire de la ei clasa C, membrii împărtășesc o clasă A comună, ca moștenire de la A declarat virtuală.

Și dacă nu a existat nici un cuvânt cheie virtuală:
clasa A
publice:
int n;
void f ();
>
clasa B1: A publică
>
clasa B2: Un public
>
clasa C: B1 publică, B2 publică
>

în membrii clasei C din clasa A «înmulțit» a (separat pentru moștenire prin B1 și separat pentru moștenire prin B2). Pentru fiecare „copie“ poate fi accesată prin specificarea numelui clasei de bază, prin care membrul a fost moștenită. De exemplu,
C * x = new C ();
x-> B1 :: f ();