C++ Polimorfism cu Exemplu
รn ce este polimorfismul C++?
In C++, polimorfismul face ca o funcศie membru sฤ se comporte diferit รฎn funcศie de obiectul care o apeleazฤ/invocฤ. Polimorfismul este un cuvรขnt grecesc care รฎnseamnฤ a avea mai multe forme. Apare atunci cรขnd aveศi o ierarhie de clase legate prin moศtenire.
De exemplu, sฤ presupunem cฤ avem funcศia makeSound(). Cรขnd o pisicฤ apeleazฤ aceastฤ funcศie, va produce sunetul miau. Atunci cรขnd o vacฤ invocฤ aceeaศi funcศie, va furniza sunetul de cosuit.
Deศi avem o singurฤ funcศie, aceasta se comportฤ diferit รฎn diferite circumstanศe. Funcศia are multe forme; prin urmare, am atins polimorfismul.
Tipuri de polimorfism
C++ suportฤ douฤ tipuri de polimorfism:
- polimorfism รฎn timp de compilare ศi
- Polimorfismul runtime.
Polimorfismul timpului de compilare
Invocaศi funcศiile supraรฎncฤrcate prin potrivirea numฤrului ศi tipului de argumente. Informaศiile sunt prezente รฎn timpul compilฤrii. Aceasta รฎnseamnฤ C++ compilatorul va selecta funcศia potrivitฤ รฎn timpul compilฤrii.
Polimorfismul รฎn timp de compilare se realizeazฤ prin supraรฎncฤrcarea funcศiilor ศi supraรฎncฤrcarea operatorului.
Supraรฎncฤrcarea funcศiei
Supraรฎncฤrcarea funcศiilor apare atunci cรขnd avem multe funcศii cu nume similare, dar cu argumente diferite. Argumentele pot diferi รฎn ceea ce priveศte numฤrul sau tipul.
Exemplu 1
#include <iostream>
using namespace std;
void test(int i) {
cout << " The int is " << i << endl;
}
void test(double f) {
cout << " The float is " << f << endl;
}
void test(char const *ch) {
cout << " The char* is " << ch << endl;
}
int main() {
test(5);
test(5.5);
test("five");
return 0;
}
ieศire:
Iatฤ o capturฤ de ecran a codului:
Explicaศia codului:
- Includeศi fiศierul antet iostream รฎn codul nostru. Vom putea folosi funcศiile sale.
- Includeศi spaศiul de nume std รฎn codul nostru. Vom putea folosi clasele sale fฤrฤ a-l apela.
- Creaศi o funcศie numitฤ test care ia un parametru รฎntreg i. { marcheazฤ รฎnceputul corpului testului funcศional.
- Declaraศie care trebuie executatฤ dacฤ testul funcศiei de mai sus este invocat/apelat.
- Sfรขrศitul corpului testului funcศional de mai sus.
- Creaศi o funcศie numitฤ test care ia un parametru float f. { marcheazฤ รฎnceputul corpului testului funcศional.
- Declaraศie care trebuie executatฤ dacฤ testul funcศiei de mai sus este invocat/apelat.
- Sfรขrศitul corpului testului funcศional de mai sus.
- Creaศi o funcศie numitฤ test care ia un parametru de caracter ch. { marcheazฤ รฎnceputul corpului testului funcศional.
- Declaraศie care trebuie executatฤ dacฤ testul funcศiei de mai sus este invocat/apelat.
- Sfรขrศitul corpului testului funcศional de mai sus.
- Apelaศi funcศia main(). { marcheazฤ รฎnceputul corpului funcศiei.
- Apelaศi testul funcศiei ศi treceศi-i 5 ca valoare a argumentului. Aceasta invocฤ funcศia de testare care acceptฤ un argument รฎntreg, adicฤ prima funcศie de testare.
- Apelaศi testul funcศiei ศi treceศi-i 5.5 ca valoare a argumentului. Aceasta va invoca funcศia de testare care acceptฤ un argument flotant, adicฤ a doua funcศie de testare.
- Apelaศi testul funcศiei ศi treceศi-i cinci ca valoare a argumentului. Aceasta va invoca funcศia de testare care acceptฤ un argument caracter, adicฤ a treia funcศie de testare.
- Programul trebuie sฤ returneze o valoare dacฤ ruleazฤ cu succes.
- Sfรขrศitul corpului funcศiei main().
Avem trei funcศii cu acelaศi nume, dar diferite tipuri de argumente. Am atins polimorfismul.
Operator Supraรฎncฤrcare
In Operator Supraรฎncฤrcare, definim un nou sens pentru a C++ operator. De asemenea, schimbฤ modul รฎn care lucreazฤ operatorul. De exemplu, putem defini operatorul + pentru a concatena douฤ ศiruri. รl ศtim ca operator de adunare pentru adฤugarea de valori numerice. Dupฤ definiศia noastrฤ, atunci cรขnd este plasat รฎntre numere รฎntregi, le va adฤuga. Cรขnd este plasat รฎntre ศiruri, le va concatena.
Exemplu 2
#include<iostream>
using namespace std;
class ComplexNum {
private:
int real, over;
public:
ComplexNum(int rl = 0, int ov = 0) {
real = rl;
over = ov;
}
ComplexNum operator + (ComplexNum const &obj) {
ComplexNum result;
result.real = real + obj.real;
result.over = over + obj.over;
return result;
}
void print() {
cout << real << " + i" << over << endl;
}
};
int main()
{
ComplexNum c1(10, 2), c2(3, 7);
ComplexNum c3 = c1+c2;
c3.print();
}
ieศire:
Iatฤ o capturฤ de ecran a codului:
Explicaศia codului:
- Includeศi fiศierul antet iostream รฎn programul nostru pentru a utiliza funcศiile acestuia.
- Includeศi spaศiul de nume std รฎn programul nostru pentru a utiliza clasele sale fฤrฤ a-l apela.
- Creaศi o clasฤ numitฤ ComplexNum. { marcheazฤ รฎnceputul corpului clasei.
- Utilizaศi modificatorul de acces privat pentru a marca variabilele ca private, ceea ce รฎnseamnฤ cฤ pot fi accesate numai din cadrul clasei.
- Definiศi douฤ variabile รฎntregi, reale ศi peste.
- Utilizaศi modificatorul de acces public pentru a marca constructorul ca public, ceea ce รฎnseamnฤ cฤ va fi accesibil chiar ศi din afara clasฤ.
- Creaศi constructorul clasei ศi iniศializaศi variabilele.
- Iniศializaศi valoarea variabilei real.
- Iniศializaศi valoarea variabilei peste.
- Sfรขrศitul corpului constructorului.
- Trebuie sฤ suprascriem semnificaศia operatorului +.
- Creaศi rezultatul tipului de date de tip ComplexNum.
- Utilizaศi operatorul + cu numere complexe. Aceastฤ linie va adฤuga partea realฤ a unui numฤr la partea realฤ a altui numฤr.
- Utilizaศi operatorul + cu numere complexe. Aceastฤ linie va adฤuga partea imaginarฤ a unui numฤr la partea imaginarฤ a altui numฤr.
- Programul va returna valoarea rezultatului variabilei la executarea cu succes.
- Sfรขrศitul definiศiei noului sens al operatorului +, adicฤ supraรฎncฤrcarea.
- Apelaศi metoda print().
- Tipฤriศi noul numฤr complex dupฤ adฤugare pe consolฤ.
- Sfรขrศitul corpului funcศiei print().
- Sfรขrศitul corpului clasei ComplexNum.
- Apelaศi funcศia main().
- Transmiteศi valorile atรขt ale pฤrศilor reale, cรขt ศi ale pฤrศilor complexe care urmeazฤ sฤ fie adฤugate. Prima parte a lui c1 va fi adฤugatฤ la prima parte a lui c2, adicฤ 10+3. A doua parte a lui c1 va fi adฤugatฤ la a doua parte a lui c, adicฤ 2+7.
- Efectuaศi o operaศie folosind operatorul supraรฎncฤrcat + ศi stocรขnd rezultatul รฎn variabila c3.
- Tipฤriศi valoarea variabilei c3 pe consolฤ.
- Sfรขrศitul corpului funcศiei main().
Polimorfismul รฎn timpul rulฤrii
Acest lucru se รฎntรขmplฤ atunci cรขnd metoda unui obiect este invocatฤ/apelatฤ รฎn timpul rulฤrii, mai degrabฤ decรขt รฎn โโtimpul compilฤrii. Polimorfismul runtime se realizeazฤ prin suprascrierea funcศiei. Funcศia care trebuie apelatฤ/invocatฤ este stabilitฤ รฎn timpul rulฤrii.
Suprascrierea funcศiei
Suprascrierea funcศiei are loc atunci cรขnd unei funcศii a clasei de bazฤ i se dฤ o nouฤ definiศie รฎntr-o clasฤ derivatฤ. รn acel moment, putem spune cฤ funcศia de bazฤ a fost รฎnlocuitฤ.
De exemplu:
#include <iostream>
using namespace std;
class Mammal {
public:
void eat() {
cout << "Mammals eat...";
}
};
class Cow: public Mammal {
public:
void eat() {
cout << "Cows eat grass...";
}
};
int main(void) {
Cow c = Cow();
c.eat();
return 0;
}
ieศire:
Iatฤ o capturฤ de ecran a codului:
Explicaศia codului:
- Importaศi fiศierul antet iostream รฎn programul nostru pentru a utiliza funcศiile acestuia.
- Includeศi spaศiul de nume std รฎn programul nostru pentru a utiliza clasele sale fฤrฤ a-l apela.
- Creaศi o clasฤ numitฤ Mamifer. { marcheazฤ รฎnceputul corpului clasei.
- Utilizaศi modificatorul de acces public pentru a seta funcศia pe care urmeazฤ sฤ o creฤm ca fiind accesibilฤ publicului. Acesta va fi accesibil din afara acestei clase.
- Creaศi o funcศie publicฤ numitฤ eat. { marcheazฤ รฎnceputul corpului funcศiei.
- Imprimaศi instrucศiunea adฤugatฤ la funcศia cout cรขnd este invocatฤ funcศia eat().
- Sfรขrศitul corpului funcศiei eat().
- Sfรขrศitul corpului clasei Mamifer.
- Creaศi o clasฤ numitฤ Cow care moศteneศte clasa Mammal. Vaca este clasa derivatฤ, รฎn timp ce Mamiferul este clasa de bazฤ. { marcheazฤ รฎnceputul acestei clase.
- Utilizaศi modificatorul de acces public pentru a marca funcศia pe care urmeazฤ sฤ o creฤm ca fiind accesibilฤ publicului. Acesta va fi accesibil din afara acestei clase.
- Ignoraศi funcศia eat() care a fost definitฤ รฎn clasa de bazฤ. { marcheazฤ รฎnceputul corpului funcศiei.
- Declaraศia de tipฤrit pe consolฤ atunci cรขnd aceastฤ funcศie este invocatฤ.
- Sfรขrศitul corpului funcศiei eat().
- Sfรขrศitul corpului clasei Vaca.
- Apelaศi funcศia main(). { marcheazฤ รฎnceputul corpului acestei funcศii.
- Creaศi o instanศฤ a clasei Cow ศi dรขndu-i numele c.
- Apelaศi funcศia eat() definitฤ รฎn clasa Cow.
- Programul trebuie sฤ returneze o valoare la finalizarea cu succes.
- Sfรขrศitul funcศiei main().
C++ Funcศia virtualฤ
O funcศie virtualฤ este o altฤ modalitate de implementare a polimorfismului รฎn timp de rulare รฎn C++. Este o funcศie specialฤ definitฤ รฎntr-o clasฤ de bazฤ ศi redefinitฤ รฎn clasa derivatฤ. Pentru a declara o funcศie virtualฤ, ar trebui sฤ utilizaศi cuvรขntul cheie virtual. Cuvรขntul cheie ar trebui sฤ preceadฤ declararea funcศiei รฎn clasa de bazฤ.
Dacฤ o clasฤ de funcศie virtualฤ este moศtenitฤ, clasa virtualฤ redefineศte funcศia virtualฤ pentru a se potrivi nevoilor sale. De exemplu:
#include <iostream>
using namespace std;
class ClassA {
public:
virtual void show() {
cout << "The show() function in base class invoked..." << endl;
}
};
class ClassB :public ClassA {
public:
void show() {
cout << "The show() function in derived class invoked...";
}
};
int main() {
ClassA* a;
ClassB b;
a = &b;
a->show();
}
ieศire:
Iatฤ o capturฤ de ecran a codului:
Explicaศia codului:
- Includeศi fiศierul antet iostream รฎn cod pentru a utiliza funcศiile acestuia.
- Includeศi spaศiul de nume std รฎn codul nostru pentru a-i folosi clasele fฤrฤ a-l apela.
- Creaศi o clasฤ numitฤ ClassA.
- Utilizaศi modificatorul de acces public pentru a marca un membru al clasei ca fiind accesibil public.
- Creaศi o funcศie virtualฤ numitฤ show(). Va fi o funcศie publicฤ.
- Textul de imprimat atunci cรขnd show() invocat este invocat. Sfรขrศitul este a C++ cuvรขnt cheie, care รฎnseamnฤ linia finalฤ. Mutฤ โโcursorul mouse-ului pe linia urmฤtoare.
- Sfรขrศitul corpului funcศiei virtuale show().
- Sfรขrศitul corpului clasei ClassA.
- Crearea unei noi clase numite ClassB care moศteneศte clasa ClassA. ClassA devine clasa de bazฤ, รฎn timp ce ClassB devine clasa derivatฤ.
- Utilizaศi modificatorul de acces public pentru a marca un membru al clasei ca fiind accesibil public.
- Redefiniศi funcศia virtualฤ show() derivatฤ รฎn clasa de bazฤ.
- Textul de tipฤrit pe consolฤ cรขnd este invocatฤ funcศia show() definitฤ รฎn clasa derivatฤ.
- Sfรขrศitul corpului funcศiei show().
- Sfรขrศitul corpului clasei derivate, ClassB.
- Apelaศi funcศia main(). Logica programului ar trebui adฤugatฤ รฎn corpul sฤu.
- Creaศi o variabilฤ pointer numitฤ a. Indicฤ clasa numitฤ ClassA.
- Creaศi o instanศฤ a clasei numitฤ ClassB. Instanศa primeศte numele b.
- Atribuiศi stocurile de valori รฎn adresa b รฎn variabila a.
- Invocaศi funcศia show() definitฤ รฎn clasa derivatฤ. Legarea tardivฤ a fost implementatฤ.
- Sfรขrศitul corpului funcศiei main().
Polimorfismul รฎn timp de compilare vs. Polimorfismul รฎn timp de rulare
Iatฤ diferenศele majore dintre cele douฤ:
| Polimorfism รฎn timp de compilare | Polimorfismul timpului de rulare |
|---|---|
| Se mai numeศte legare timpurie sau polimorfism static | Se mai numeศte legare tardivฤ/dinamicฤ sau polimorfism dinamic |
| Metoda este apelatฤ/invocatฤ รฎn timpul compilฤrii | Metoda este apelatฤ/invocatฤ รฎn timpul rulฤrii |
| Implementat prin supraรฎncฤrcarea funcศiilor ศi supraรฎncฤrcarea operatorului | Implementat prin suprascrierea metodei ศi funcศii virtuale |
| De exemplu, supraรฎncฤrcarea metodei. Multe metode pot avea nume similare, dar numฤr sau tipuri diferite de argumente | Exemplu, รฎnlocuirea metodei. Multe metode pot avea un nume similar ศi acelaศi prototip. |
| Execuศie mai rapidฤ, deoarece descoperirea metodelor se face รฎn timpul compilฤrii | Execuศie mai lentฤ, deoarece metoda de descoperire se face รฎn timpul rulฤrii. |
| Less este oferitฤ flexibilitate pentru rezolvarea problemelor, deoarece totul este cunoscut รฎn timpul compilฤrii. | Este oferitฤ multฤ flexibilitate pentru rezolvarea problemelor complexe, deoarece metodele sunt descoperite รฎn timpul rulฤrii. |
Rezumat
- Polimorfismul รฎnseamnฤ a avea mai multe forme.
- Apare atunci cรขnd existฤ o ierarhie a claselor legate prin moศtenire.
- Cu polimorfism, o funcศie se poate comporta diferit รฎn funcศie de obiectul care o invocฤ/o chema.
- รn polimorfismul รฎn timp de compilare, funcศia care trebuie invocatฤ este stabilitฤ รฎn timpul compilฤrii.
- รn polimorfismul runtime, funcศia care trebuie invocatฤ este stabilitฤ รฎn timpul rulฤrii.
- Polimorfismul รฎn timp de compilare este determinat prin supraรฎncฤrcarea funcศiilor ศi supraรฎncฤrcarea operatorului.
- รn supraรฎncฤrcarea funcศiilor, existฤ multe funcศii cu nume similare, dar cu argumente diferite.
- Parametrii pot diferi ca numฤr sau tip.
- รn supraรฎncฤrcarea operatorului, este definit un nou sens pentru C++ Operatorii.
- Polimorfismul runtime se realizeazฤ prin suprascrierea funcศiei.
- รn suprascrierea funcศiei, o clasฤ derivatฤ oferฤ o nouฤ definiศie unei funcศii definite รฎn clasa de bazฤ.







