Video: ? Programare Orientata pe Obiecte: Cum se folosesc Clasele in Java | Programare in Java #5 2024
C ++ suportă întârzierea legării , care este atunci când rezolvă un apel de metodă bazat pe timpul de execuție tip (sau tip dinamic) al obiectului țintă, mai degrabă decât tipul său declarat (sau tipul static). Acest lucru este demonstrat în următorul fragment de cod C ++:
#include utilizând namespace std; clasa Cuptor {public: virtual void cook () {cout << "gătit cu un cuptor" << endl;}}; clasa microundeOven: cuptor public {public: virtual void cook () {cout << "gătit cu un cuptor cu microunde" << endl;}}; void prepareMeal (cuptor și cuptor) {cuptor. cook ();}
În funcția prepareMeal (), apelul în cuptor. bucătar () poate trece în cuptor:: bucătar () sau cuptor cu microunde:: cook () în funcție de timpul de funcționare (tipul "real") al obiectului cuptorului trecut.
Cuvântul cheie virtuală este esențial aici. Fără aceasta, metoda cook () va fi legată mai devreme, pe baza tipului de timp de compilare și va invoca cuptorul:: cook () de fiecare dată. După ce a fost declarat virtual în clasa Cuptor, metoda se presupune a fi virtuală în fiecare subclasă, dar nu rănește să repetați declarația astfel încât cititorii să înțeleagă.
Următorul program simplu demonstrează acest principiu în practică:
int principal () {Cuptor cuptor; prepareMeal (cuptor); Cuptor cu microunde; prepareMeal (mo); retur 0;}
În acest program, apelul pentru gătit () generează două ieșiri diferite în funcție de tipul cuptorului:
Gătit cu un cuptor Gătit cu un cuptor cu microunde
că o metodă din clasa de bază poate fi definită. Luați în considerare cazanul cu mai multă atenție. Există o serie de tipuri diferite de cuptoare - cuptoare convenționale, cuptoare de convecție și cuptoare cu microunde - dar se poate susține că nu există nici un cuptor real care să nu aparțină uneia dintre aceste subclase. Este posibil să puteți spune cum diferite tipuri de cuptoare efectuează operația de preparare a gătitului - adică, ce ar trebui să definească un modul de gătit () și un cuptor cu microunde. Probabil nu este posibil să definiți ce acțiuni ar trebui să fie executate de cuptor:: cook ().
Nu puteți lăsa pur și simplu cuptorul:: cook () nedeclarat într-un limbaj puternic, precum C ++. Cu toate acestea, puteți declara o metodă, dar lăsați-o neimplementată dacă nu există nicio implementare. Se utilizează următoarea sintaxă curioasă:
Cuptor de clasă {public: virtual void cook () = 0;};
Acest cod declară o metodă Cuptor:: cook () care este legat târziu, dar nu implementează metoda. De fapt, merge mai departe spunând că metoda nu va fi pusă în aplicare. În C ++, o astfel de metodă se consideră a fi virtuală pură . Programatorii C ++ utilizează de asemenea termenul preferat în multe alte limbi de calculator puternic tipizate: abstract .Clasa cuptorului este considerată a fi abstractă.
Un rezumat reprezintă o proprietate pe care o cunoașteți clasa posedată, dar nu știți cum să o implementați fără echivoc în clasa actuală.
O clasă este abstractă dacă conține una sau mai multe metode virtuale pure. Semnificația acestui lucru este că nu puteți instanțiza o clasă abstractă. Astfel nu mai sunt permise urmatoarele:
int main () {Cuptor cu cuptor; prepareMeal (cuptor); retur 0;}
Motivul pentru aceasta este simplu: dacă ați creat un obiect de cuptor de clasă și apoi ați încercat să invocați cuptorul. cook (), ce ar trebui să facă compilatorul?
La un nivel mai filosofic, este bine să spunem că există un termen comun denumit Cuptor care descrie cuptoare convenționale și cuptoare cu microunde și cuptoare de convecție. Acest termen Cuptor este un concept obișnuit, deoarece leagă asemănările din toate aceste subclase. Dar nu există nici un exemplu de cuptor care nu este una dintre subclasele cuptorului.
O subclasă a unei clase abstracte este ea însăși abstractă până când toate metodele virtuale pure au fost suprascrise de versiuni non-abstracte (adică beton ). Astfel, clasa MicrowaveOven din fragmentul de cod anterior nu este abstractă - chiar dacă cuptorul a fost abstract - deoarece înlocuiește cook () cu versiunea sa proprie.
Observați că nu este nimic în neregulă cu funcția prepareMeal () definită după cum urmează:
void prepareMeal (cuptor și cuptor) {cuptor. cook ();}
Chiar dacă argumentul este declarat a fi un cuptor, el poate fi invocat numai cu o anumită subclasă a cuptorului, cum ar fi Cuptorul cu microunde sau ConventionalOven, pentru care este definit cook ().