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.

 Polimorfismul în C++

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.

Tipuri de polimorfism

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:

Supraîncărcarea funcției

Iată o captură de ecran a codului:

Supraîncărcarea funcției

Explicația codului:

  1. Includeți fișierul antet iostream în codul nostru. Vom putea folosi funcțiile sale.
  2. Includeți spațiul de nume std în codul nostru. Vom putea folosi clasele sale fără a-l apela.
  3. Creați o funcție numită test care ia un parametru întreg i. { marchează începutul corpului testului funcțional.
  4. Declarație care trebuie executată dacă testul funcției de mai sus este invocat/apelat.
  5. Sfârșitul corpului testului funcțional de mai sus.
  6. Creați o funcție numită test care ia un parametru float f. { marchează începutul corpului testului funcțional.
  7. Declarație care trebuie executată dacă testul funcției de mai sus este invocat/apelat.
  8. Sfârșitul corpului testului funcțional de mai sus.
  9. Creați o funcție numită test care ia un parametru de caracter ch. { marchează începutul corpului testului funcțional.
  10. Declarație care trebuie executată dacă testul funcției de mai sus este invocat/apelat.
  11. Sfârșitul corpului testului funcțional de mai sus.
  12. Apelați funcția main(). { marchează începutul corpului funcției.
  13. 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.
  14. 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.
  15. 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.
  16. Programul trebuie să returneze o valoare dacă rulează cu succes.
  17. 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:

Operator Supraîncărcare

Iată o captură de ecran a codului:

Operator Supraîncărcare

Operator Supraîncărcare

Explicația codului:

  1. Includeți fișierul antet iostream în programul nostru pentru a utiliza funcțiile acestuia.
  2. Includeți spațiul de nume std în programul nostru pentru a utiliza clasele sale fără a-l apela.
  3. Creați o clasă numită ComplexNum. { marchează începutul corpului clasei.
  4. Utilizați modificatorul de acces privat pentru a marca variabilele ca private, ceea ce înseamnă că pot fi accesate numai din cadrul clasei.
  5. Definiți două variabile întregi, reale și peste.
  6. Utilizați modificatorul de acces public pentru a marca constructorul ca public, ceea ce înseamnă că va fi accesibil chiar și din afara clasă.
  7. Creați constructorul clasei și inițializați variabilele.
  8. Inițializați valoarea variabilei real.
  9. Inițializați valoarea variabilei peste.
  10. Sfârșitul corpului constructorului.
  11. Trebuie să suprascriem semnificația operatorului +.
  12. Creați rezultatul tipului de date de tip ComplexNum.
  13. Utilizați operatorul + cu numere complexe. Această linie va adăuga partea reală a unui număr la partea reală a altui număr.
  14. Utilizați operatorul + cu numere complexe. Această linie va adăuga partea imaginară a unui număr la partea imaginară a altui număr.
  15. Programul va returna valoarea rezultatului variabilei la executarea cu succes.
  16. Sfârșitul definiției noului sens al operatorului +, adică supraîncărcarea.
  17. Apelați metoda print().
  18. Tipăriți noul număr complex după adăugare pe consolă.
  19. Sfârșitul corpului funcției print().
  20. Sfârșitul corpului clasei ComplexNum.
  21. Apelați funcția main().
  22. 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.
  23. Efectuați o operație folosind operatorul supraîncărcat + și stocând rezultatul în variabila c3.
  24. Tipăriți valoarea variabilei c3 pe consolă.
  25. 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:

Suprascrierea funcției

Iată o captură de ecran a codului:

Suprascrierea funcției

Explicația codului:

  1. Importați fișierul antet iostream în programul nostru pentru a utiliza funcțiile acestuia.
  2. Includeți spațiul de nume std în programul nostru pentru a utiliza clasele sale fără a-l apela.
  3. Creați o clasă numită Mamifer. { marchează începutul corpului clasei.
  4. 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.
  5. Creați o funcție publică numită eat. { marchează începutul corpului funcției.
  6. Imprimați instrucțiunea adăugată la funcția cout când este invocată funcția eat().
  7. Sfârșitul corpului funcției eat().
  8. Sfârșitul corpului clasei Mamifer.
  9. 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.
  10. 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.
  11. Ignorați funcția eat() care a fost definită în clasa de bază. { marchează începutul corpului funcției.
  12. Declarația de tipărit pe consolă atunci când această funcție este invocată.
  13. Sfârșitul corpului funcției eat().
  14. Sfârșitul corpului clasei Vaca.
  15. Apelați funcția main(). { marchează începutul corpului acestei funcții.
  16. Creați o instanță a clasei Cow și dându-i numele c.
  17. Apelați funcția eat() definită în clasa Cow.
  18. Programul trebuie să returneze o valoare la finalizarea cu succes.
  19. 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:

C++ Funcția virtuală

Iată o captură de ecran a codului:

C++ Funcția virtuală

Explicația codului:

  1. Includeți fișierul antet iostream în cod pentru a utiliza funcțiile acestuia.
  2. Includeți spațiul de nume std în codul nostru pentru a-i folosi clasele fără a-l apela.
  3. Creați o clasă numită ClassA.
  4. Utilizați modificatorul de acces public pentru a marca un membru al clasei ca fiind accesibil public.
  5. Creați o funcție virtuală numită show(). Va fi o funcție publică.
  6. 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.
  7. Sfârșitul corpului funcției virtuale show().
  8. Sfârșitul corpului clasei ClassA.
  9. Crearea unei noi clase numite ClassB care moștenește clasa ClassA. ClassA devine clasa de bază, în timp ce ClassB devine clasa derivată.
  10. Utilizați modificatorul de acces public pentru a marca un membru al clasei ca fiind accesibil public.
  11. Redefiniți funcția virtuală show() derivată în clasa de bază.
  12. Textul de tipărit pe consolă când este invocată funcția show() definită în clasa derivată.
  13. Sfârșitul corpului funcției show().
  14. Sfârșitul corpului clasei derivate, ClassB.
  15. Apelați funcția main(). Logica programului ar trebui adăugată în corpul său.
  16. Creați o variabilă pointer numită a. Indică clasa numită ClassA.
  17. Creați o instanță a clasei numită ClassB. Instanța primește numele b.
  18. Atribuiți stocurile de valori în adresa b în variabila a.
  19. Invocați funcția show() definită în clasa derivată. Legarea tardivă a fost implementată.
  20. 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ă.

Rezumați această postare cu: