polymorphism c
Ruolo del polimorfismo in C ++ con esempi.
Il polimorfismo è uno dei quattro pilastri della programmazione orientata agli oggetti. Il polimorfismo significa avere molte forme. Può essere definita come la tecnica con cui un oggetto può assumere molte forme a seconda della situazione.
In termini di programmazione, possiamo dire che un oggetto può comportarsi in modo diverso in condizioni diverse.
In questo tutorial, impareremo i tipi di polimorfismo, i modi per implementare il polimorfismo insieme ai vari altri concetti di polimorfismo in dettaglio.
=> Controlla qui per vedere i tutorial di formazione dalla A alla Z di C ++ qui.
Per esempio, una donna può assumere molti ruoli in diverse situazioni. Per un bambino è una madre, una casalinga a casa, una lavoratrice in ufficio, ecc. Quindi una donna assume ruoli diversi e mostra comportamenti diversi in condizioni diverse. Questo è un esempio reale di polimorfismo.
Allo stesso modo anche nel mondo della programmazione, possiamo avere un operatore “+” ovvero l'operatore di addizione binaria che si comporta diversamente quando gli operandi cambiano. Per esempio, quando entrambi gli operandi sono numerici, esegue l'addizione.
D'altra parte, quando gli operandi sono stringa, agisce come operatore di concatenazione. Quindi polimorfismo, in poche parole, significa un'entità che assume molte forme o si comporta in modo diverso in condizioni diverse.
Cosa imparerai:
- Tipi di polimorfismo
- Compile Time Polymorphism vs. Polimorfismo di runtime
- Compile Time Polymorphism
- Funzione sovraccarico
- Sovraccarico dell'operatore
- Conclusione
- Lettura consigliata
Tipi di polimorfismo
Il polimorfismo è diviso in due tipi.
- Compilare il polimorfismo del tempo
- Polimorfismo a runtime
Il diagramma per rappresentarlo è mostrato di seguito:
Come mostrato nel diagramma sopra, il polimorfismo è diviso in polimorfismo in fase di compilazione e polimorfismo a runtime. Il polimorfismo in fase di compilazione è ulteriormente suddiviso in sovraccarico dell'operatore e sovraccarico della funzione. Il polimorfismo di runtime è ulteriormente implementato utilizzando funzioni virtuali.
Il polimorfismo in fase di compilazione è anche noto come polimorfismo di associazione anticipata o statico. In questo tipo di polimorfismo, il metodo dell'oggetto viene invocato in fase di compilazione. Nel caso del polimorfismo a runtime, il metodo dell'oggetto viene richiamato in fase di runtime.
Il polimorfismo di runtime è anche noto come legame dinamico o tardivo o polimorfismo dinamico. Esamineremo l'implementazione dettagliata di ciascuna di queste tecniche nei nostri argomenti seguenti.
Compile Time Polymorphism vs. Polimorfismo di runtime
Vediamo di seguito le principali differenze tra il tempo di compilazione e il polimorfismo di runtime.
Compilare il polimorfismo del tempo | Polimorfismo a runtime |
---|---|
Conosciuto anche come polimorfismo statico o associazione anticipata | Conosciuto anche come polimorfismo dinamico o associazione tardiva / dinamica |
Il metodo degli oggetti viene richiamato in fase di compilazione | Il metodo dell'oggetto viene richiamato in fase di esecuzione |
Solitamente implementato utilizzando il sovraccarico dell'operatore e il sovraccarico della funzione | Implementato utilizzando funzioni virtuali e override del metodo |
Il sovraccarico del metodo è un polimorfismo in fase di compilazione in cui più di un metodo può avere lo stesso nome ma diversi tipi e elenchi di parametri. | L'override del metodo è il polimorfismo di runtime in cui più di un metodo ha lo stesso nome con lo stesso prototipo |
Poiché i metodi sono noti in fase di compilazione, l'esecuzione è più veloce | L'esecuzione è più lenta poiché il metodo è noto in fase di esecuzione |
Fornire meno flessibilità per implementare soluzioni poiché tutto deve essere conosciuto in fase di compilazione | Molto più flessibile per l'implementazione di soluzioni complesse poiché i metodi vengono decisi in fase di esecuzione |
Compile Time Polymorphism
Il polimorfismo in fase di compilazione è una tecnica in cui il metodo di un oggetto viene richiamato in fase di compilazione.
Questo tipo di polimorfismo viene implementato in due modi.
- Sovraccarico delle funzioni
- Sovraccarico dell'operatore
Discuteremo ogni tecnica in dettaglio.
Funzione sovraccarico
Si dice che una funzione viene sovraccaricata quando abbiamo più di una funzione con lo stesso nome ma diversi tipi di parametro o un diverso numero di argomenti.
Pertanto una funzione può essere sovraccaricata in base ai tipi di parametro, all'ordine dei parametri e al numero di parametri.
Si noti che due funzioni con lo stesso nome e lo stesso elenco di parametri ma un diverso tipo restituito non è una funzione sovraccarica e, se utilizzata nel programma, risulterà in un errore di compilazione.
Allo stesso modo, quando i parametri della funzione differiscono solo nel puntatore e se il tipo di matrice è equivalente, non deve essere utilizzato per il sovraccarico.
Altri tipi come statico e non statico, const e volatile, ecc. Oppure le dichiarazioni di parametri che differiscono in presenza o assenza di valori di default non devono essere utilizzate per il sovraccarico in quanto sono equivalenti dal punto di vista dell'implementazione.
Per esempio,i seguenti prototipi di funzione sono funzioni sovraccaricate.
Add(int,int); Add(int,float); Add(float,int); Add(int,int,int);
Nei prototipi sopra, vediamo che sovraccarichiamo la funzione Aggiungi in base al tipo di parametri, sequenza o ordine dei parametri, numero di parametri, ecc.
Prendiamo un esempio di programmazione completo per comprendere meglio il sovraccarico delle funzioni.
#include #include using namespace std; class Summation { public: int Add(int num1,int num2) { return num1+num2; } int Add(int num1,int num2, int num3) { return num1+num2+num3; } string Add(string s1,string s2){ return s1+s2; } }; int main(void) { Summation obj; cout< Produzione:
35
191
19
Ciao mondo
Nel programma precedente, abbiamo una classe Summation che definisce tre funzioni sovraccaricate denominate Add che accetta due argomenti interi, tre argomenti interi e due argomenti stringa.
Nella funzione principale, effettuiamo quattro chiamate di funzione che forniscono vari parametri. Le prime due chiamate di funzione sono semplici. Nella terza chiamata di funzione ad Add, forniamo due valori in virgola mobile come argomenti.
In questo caso, la funzione corrispondente è int Add (int, int) poiché internamente, il float viene convertito in double e quindi abbinato alla funzione con i parametri int. Se avessimo specificato double invece di float, avremmo un'altra funzione sovraccaricata con double come parametri.
L'ultima chiamata di funzione utilizza valori stringa come parametri. In questo caso, l'operatore Aggiungi (+) funge da operatore di concatenazione e concatena i due valori di stringa per produrre una singola stringa.
Vantaggi del sovraccarico delle funzioni
Il vantaggio principale del sovraccarico delle funzioni è che promuove la riusabilità del codice. Possiamo avere quante più funzioni possibili con lo stesso nome purché siano sovraccaricate in base al tipo di argomento, alla sequenza di argomenti e al numero di argomenti.
puoi usare qualsiasi auricolare vr per ps4
In questo modo diventa più facile avere funzioni diverse con lo stesso nome per rappresentare il comportamento della stessa operazione in condizioni diverse.
Se il sovraccarico delle funzioni non fosse presente, avremmo dovuto scrivere troppi tipi diversi di funzioni con nomi diversi, rendendo così il codice illeggibile e difficile da adattare.
Sovraccarico dell'operatore
L'overloading degli operatori è la tecnica con cui diamo un significato diverso agli operatori esistenti in C ++. In altre parole, sovraccarichiamo gli operatori per dare un significato speciale ai tipi di dati definiti dall'utente come oggetti.
La maggior parte degli operatori in C ++ sono sovraccaricati o hanno un significato speciale in modo che possano lavorare su tipi di dati definiti dall'utente. Notare che durante il sovraccarico, il funzionamento di base degli operatori non viene alterato. Il sovraccarico fornisce all'operatore un significato aggiuntivo mantenendo la stessa semantica di base.
Sebbene la maggior parte degli operatori possa essere sovraccaricata in C ++, ci sono alcuni operatori che non possono essere sovraccaricati.
Questi operatori sono elencati nella tabella seguente.
Operatori Operatore di risoluzione dell'ambito (: :) Taglia di selettore membri (.) selettore puntatore membro (*) operatore ternario (? :)
Le funzioni che utilizziamo per sovraccaricare gli operatori sono chiamate ' Funzioni operatore '.
Le funzioni operatore sono simili alle normali funzioni ma con una differenza. La differenza è che il nome delle funzioni dell'operatore inizia con la parola chiave ' operatore ”Seguito dal simbolo dell'operatore che deve essere sovraccaricato.
La funzione operatore viene quindi chiamata quando l'operatore corrispondente viene utilizzato nel programma. Queste funzioni operatore possono essere funzioni membro o metodi globali o anche una funzione amico.
La sintassi generale della funzione operatore è:
return_type classname::operator op(parameter list) { //function body }
Qui 'operatore op' è la funzione operatore in cui l'operatore è la parola chiave e op è l'operatore da sovraccaricare. Return_type è il tipo di valore da restituire.
Vediamo alcuni esempi di programmazione per dimostrare il sovraccarico dell'operatore utilizzando le funzioni dell'operatore.
Esempio 1:Sovraccarico dell'operatore unario utilizzando la funzione operatore membro.
#include using namespace std; class Distance { public: int feet; // Constructor to initialize the object's value Distance(int feet) { this->feet = feet; } //operator function to overload ++ operator to perform increment on Distance obj void operator++() { feet++; } void print(){ cout << '
Incremented Feet value: ' << feet; } }; int main() { Distance d1(9); // Use (++) unary operator ++d1; d1.print(); return 0; }
Produzione:
Valore in piedi incrementati: 10
Qui abbiamo sovraccaricato l'operatore di incremento unario utilizzando la funzione operator ++. Nella funzione main, usiamo questo operatore ++ per incrementare l'oggetto della classe Distance.
Esempio 2:Sovraccarico dell'operatore binario utilizzando la funzione operatore membro.
#include using namespace std; class Complex { int real, imag; public: Complex(int r = 0, int i =0) {real = r; imag = i;} //Operator function to overload binary + to add two complex numbers Complex operator + (Complex const &obj) { Complex c3; c3.real = real + obj.real; c3.imag = imag + obj.imag; return c3; } void print() { cout << real << ' + i' << imag << endl; } }; int main() { Complex c1(2, 5), c2(3, 7); cout<<'c1 = '; c1.print(); cout<<'c2 = '; c2.print(); cout<<'c3 = c1+c2 = '; Complex c3 = c1 + c2; // calls overloaded + operator c3.print(); }
Produzione:
c1 = 2 + i5
c2 = 3 + i7
c3 = c1 + c2 = 5 + i12
Qui abbiamo utilizzato il classico esempio dell'aggiunta di due numeri complessi utilizzando l'operatore di sovraccarico. Definiamo una classe per rappresentare numeri complessi e una funzione operatore per sovraccaricare + operatore in cui aggiungiamo le parti reali e immaginarie di numeri complessi.
Nella funzione principale, dichiariamo due oggetti complessi e li aggiungiamo usando l'operatore + sovraccarico per ottenere il risultato desiderato.
Nell'esempio seguente, useremo la funzione amico per aggiungere due numeri complessi per vedere la differenza nell'implementazione.
#include using namespace std; class Complex { int real, imag; public: Complex(int r = 0, int i =0) {real = r; imag = i;} //friend function to overload binary + to add two complex numbers friend Complex operator +(Complex const &, Complex const &); void print() { cout << real << ' + i' << imag << endl; } }; Complex operator + (Complex const &c1, Complex const &c2) { Complex c3; c3.real = c1.real + c2.real; c3.imag = c1.imag + c2.imag; return c3; } int main() { Complex c1(2, 5), c2(3, 7); cout<<'c1 = '; c1.print(); cout<<'c2 = '; c2.print(); cout<<'c3 = c1+c2 = '; Complex c3 = c1 + c2; // calls overloaded + operator c3.print(); }
Produzione:
c1 = 2 + i5
c2 = 3 + i7
c3 = c1 + c2 = 5 + i12
Vediamo che l'output del programma è lo stesso. L'unica differenza nell'implementazione è l'uso della funzione friend per sovraccaricare l'operatore + invece di una funzione membro nell'implementazione precedente.
Quando la funzione amico viene utilizzata per un operatore binario, dobbiamo specificare esplicitamente entrambi gli operandi della funzione. Allo stesso modo, quando l'operatore unario viene sovraccaricato utilizzando la funzione amico, è necessario fornire il singolo operando alla funzione.
Oltre alle funzioni operatore, possiamo anche scrivere un file operatore di conversione che viene utilizzato per convertire da un tipo a un altro. Questi operatori di conversione sovraccaricati dovrebbero essere una funzione membro della classe.
Esempio 3:Sovraccarico degli operatori utilizzando l'operatore di conversione.
#include using namespace std; class DecFraction { int numerator, denom; public: DecFraction(int num, int denm) { numerator = num; denom = denm; } // conversion operator: converts fraction to float value and returns it operator float() const { return float(numerator) / float(denom); } }; int main() { DecFraction df(3, 5); //object of class float res_val = df; //calls conversion operator cout << 'The resultant value of given fraction (3,5)= '< Produzione:
Il valore risultante di una data frazione (3,5) = 0,6
In questo programma, abbiamo utilizzato l'operatore di conversione per convertire la frazione data in un valore float. Una volta completata la conversione, l'operatore di conversione restituisce il valore risultante al chiamante.
Nella funzione main, quando assegniamo l'oggetto df a una variabile res_val, avviene la conversione e il risultato viene memorizzato in res_val.
Possiamo anche chiamare un costruttore con un singolo argomento. Quando possiamo chiamare un costruttore dalla classe utilizzando un singolo argomento, questo viene chiamato ' conversione costruttore '. Il costruttore di conversione può essere utilizzato per la conversione implicita nella classe in costruzione.
#include using namespace std; class Point { private: int x,y; public: Point(int i=0,int j=0) {x = i;y=j;} void print() { cout<<' x = '< Produzione:
Punto costruito utilizzando un normale costruttore
x = 20 y = 30
Punto costruito utilizzando il costruttore di conversione
x = 10 y = 0

Qui abbiamo una classe Point che definisce un costruttore con valori predefiniti. Nella funzione main, costruiamo un oggetto pt con le coordinate x e y. Successivamente, assegniamo a pt un valore di 10. Qui è dove viene chiamato il costruttore di conversione e x viene assegnato un valore di 10 mentre a y viene dato il valore predefinito di 0.
Regole di sovraccarico dell'operatore
Durante l'esecuzione del sovraccarico dell'operatore, è necessario prestare attenzione alle regole seguenti.
- In C ++, siamo in grado di sovraccaricare solo gli operatori esistenti. Gli operatori appena aggiunti non possono essere sovraccaricati.
- Quando gli operatori sono sovraccaricati, dobbiamo assicurarci che almeno uno degli operandi sia del tipo definito dall'utente.
- Per sovraccaricare alcuni operatori, possiamo anche utilizzare la funzione amico.
- Quando sovraccarichiamo gli operatori unari utilizzando una funzione membro, non accetta argomenti espliciti. Richiede un argomento esplicito quando l'operatore unario viene sovraccaricato utilizzando la funzione amico.
- Allo stesso modo, quando gli operatori binari vengono sovraccaricati utilizzando la funzione membro, dobbiamo fornire un argomento esplicito alla funzione. Quando gli operatori binari vengono sovraccaricati utilizzando la funzione amico, la funzione accetta due argomenti.
- Ci sono due operatori in C ++ che sono già sovraccaricati. Questi sono '=' e '&'. Quindi per copiare un oggetto della stessa classe, non è necessario sovraccaricare l'operatore =, e possiamo usarlo direttamente.
Vantaggi del sovraccarico dell'operatore
Il sovraccarico degli operatori in C ++ ci consente di estendere la funzionalità degli operatori ai tipi definiti dall'utente, inclusi gli oggetti classe oltre ai tipi incorporati.
Estendendo la funzionalità dell'operatore ai tipi definiti dall'utente, non abbiamo bisogno di scrivere codice complesso per eseguire varie operazioni sui tipi definiti dall'utente, ma possiamo farlo in un'unica operazione, proprio come i tipi incorporati.
Conclusione
Il polimorfismo in fase di compilazione fornisce funzionalità di sovraccarico principalmente per estendere la funzionalità del codice in termini di sovraccarico delle funzioni e sovraccarico dell'operatore.
Tramite il sovraccarico delle funzioni, possiamo scrivere più di una funzione con lo stesso nome ma parametri e tipi diversi. Ciò rende il codice semplice e facilmente leggibile. Tramite l'overloading degli operatori, possiamo estendere la funzionalità degli operatori, in modo da poter eseguire operazioni di base anche sui tipi definiti dall'utente.
Nel nostro prossimo tutorial, impareremo di più sul polimorfismo di runtime in C ++.
=> Leggi la serie di formazione Easy C ++.
Lettura consigliata
- Polimorfismo di runtime in C ++
- Funzioni Friend in C ++
- Ricorsione in C ++
- Tutorial sulle funzioni principali di Python con esempi pratici
- Una panoramica completa di C ++
- Tutorial QTP # 21 - Come rendere modulari e riutilizzabili i test QTP utilizzando azioni e librerie di funzioni
- Tutorial su Unix Pipes: Pipes nella programmazione Unix
- Funzioni di libreria in C ++