C++ Polymorfisme met voorbeeld

Wat is polymorfisme in C++?

In C++ zorgt polymorfisme ervoor dat een lidfunctie zich anders gedraagt, afhankelijk van het object dat deze aanroept/aanroept. Polymorfisme is een Grieks woord dat vele vormen betekent. Het komt voor als je een hiërarchie van klassen hebt die gerelateerd zijn door overerving.

Stel dat we bijvoorbeeld de functie makeSound() hebben. Wanneer een kat deze functie oproept, produceert hij het miauwgeluid. Wanneer een koe dezelfde functie aanroept, zal zij het miauwgeluid voortbrengen.

Polymorfisme in C ++

Hoewel we één functie hebben, gedraagt ​​deze zich onder verschillende omstandigheden anders. De functie kent vele vormen; daarom hebben we polymorfisme bereikt.

Soorten polymorfisme

C++ ondersteunt twee soorten polymorfisme:

  • Compile-time polymorfisme, en
  • Runtime-polymorfisme.

Soorten polymorfisme

Compileer tijdpolymorfisme

U roept de overbelaste functies aan door het aantal en het type argumenten te matchen. De informatie is aanwezig tijdens het compileren. Dit betekent dat de C++-compiler tijdens het compileren de juiste functie selecteert.

Compile-time polymorfisme wordt bereikt door overbelasting van functies en operaof overbelasting.

Functie Overbelasting

Overbelasting van functies treedt op als we veel functies hebben met vergelijkbare namen maar met verschillende argumenten. De argumenten kunnen verschillen qua aantal of type.

Voorbeeld 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;
}

Output:

Functie Overbelasting

Hier is een screenshot van de code:

Functie Overbelasting

Code Verklaring:

  1. Neem het iostream-headerbestand op in onze code. We zullen de functies ervan kunnen gebruiken.
  2. Neem de std-naamruimte op in onze code. We kunnen de klassen ervan gebruiken zonder deze aan te roepen.
  3. Maak een functie met de naam test waaraan een geheel getalparameter i moet doorgegeven worden. De { markeert het begin van de hoofdtekst van de functietest.
  4. Verklaring die moet worden uitgevoerd als de bovenstaande functietest wordt aangeroepen/aangeroepen.
  5. Einde van de hoofdtekst van bovenstaande functietest.
  6. Maak een functie met de naam test waaraan een float-parameter f moet doorgegeven worden. De { markeert het begin van de hoofdtekst van de functietest.
  7. Verklaring die moet worden uitgevoerd als de bovenstaande functietest wordt aangeroepen/aangeroepen.
  8. Einde van de hoofdtekst van de bovenstaande functietest.
  9. Maak een functie met de naam test waaraan een tekenparameter ch moet doorgegeven worden. De { markeert het begin van de hoofdtekst van de functietest.
  10. Verklaring die moet worden uitgevoerd als de bovenstaande functietest wordt aangeroepen/aangeroepen.
  11. Einde van de hoofdtekst van de bovenstaande functietest.
  12. Roep de functie main() aan. De { markeert het begin van de hoofdtekst van de functie.
  13. Roep de functie test op en geef er 5 aan als de waarde van het argument. Hierdoor wordt de testfunctie aangeroepen die een geheel getal-argument accepteert, dat wil zeggen de eerste testfunctie.
  14. Roep de functie test aan en geef er 5.5 aan als de waarde van het argument. Hierdoor wordt de testfunctie aangeroepen die een float-argument accepteert, dat wil zeggen de tweede testfunctie.
  15. Roep de functie test op en geef er vijf aan als de waarde van het argument. Hierdoor wordt de testfunctie aangeroepen die een karakterargument accepteert, dat wil zeggen de derde testfunctie.
  16. Het programma moet een waarde retourneren als het succesvol wordt uitgevoerd.
  17. Het einde van de hoofdtekst van de functie main().

We hebben drie functies met dezelfde naam, maar verschillende soorten argumenten. We hebben polymorfisme bereikt.

Operavoor overbelasting

In OperaVoor overbelasting definiëren we een nieuwe betekenis voor C++ operaTor. Het verandert ook hoe de operator werkt. We kunnen bijvoorbeeld de + definiëren operator om twee strings aan elkaar te koppelen. Wij kennen het als de toevoeging operator voor het toevoegen van numerieke waarden. Na onze definitie zal het, wanneer het tussen gehele getallen wordt geplaatst, deze optellen. Wanneer het tussen strings wordt geplaatst, worden ze aaneengeschakeld.

Voorbeeld 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();
}

Output:

Operavoor overbelasting

Hier is een screenshot van de code:

Operavoor overbelasting

Operavoor overbelasting

Code Verklaring:

  1. Voeg het iostream-headerbestand toe aan ons programma om de functies ervan te kunnen gebruiken.
  2. Neem de std-naamruimte op in ons programma om de klassen ervan te gebruiken zonder deze aan te roepen.
  3. Maak een klasse met de naam ComplexNum. De { markeert het begin van de hoofdtekst van de klasse.
  4. Gebruik de private access modifier om variabelen als privé te markeren, wat betekent dat ze alleen toegankelijk zijn vanuit de klasse.
  5. Definieer twee integer-variabelen, real en over.
  6. Gebruik de public access modifier om de constructor als openbaar te markeren, wat betekent dat deze zelfs van buitenaf toegankelijk is klasse.
  7. Maak de klassenconstructor en initialiseer de variabelen.
  8. Initialiseer de waarde van de variabele real.
  9. Initialiseer de waarde van de variabele over.
  10. Einde van het constructorlichaam.
  11. We moeten de betekenis van de + negeren operadoel.
  12. Maak het gegevenstyperesultaat van het type ComplexNum.
  13. Gebruik de + operator met complex numbers. Deze regel voegt het reële deel van een getal toe aan het reële deel van een ander getal.
  14. Gebruik de + operator met complex numbers. Deze regel voegt het denkbeeldige deel van een getal toe aan het denkbeeldige deel van een ander getal.
  15. Het programma retourneert de waarde van het variabele resultaat bij succesvolle uitvoering.
  16. Einde van de definitie van de nieuwe betekenis van + operator, dat wil zeggen overbelasting.
  17. Roep de methode print() aan.
  18. Druk de nieuwe com afplex nummer na toevoeging op de console.
  19. Einde van de hoofdtekst van de functie print().
  20. Einde van het lichaam van ComplexNum klasse.
  21. Roep de functie main() aan.
  22. Geef de waarden van zowel real als com doorplex onderdelen toe te voegen. Het eerste deel van c1 wordt toegevoegd aan het eerste deel van c2, dat wil zeggen 10+3. Het tweede deel van c1 wordt opgeteld bij het tweede deel van c, dat wil zeggen 2+7.
  23. Voer een operamet behulp van de overbelaste + operator en het resultaat opslaan in variabele c3.
  24. Druk de waarde van variabele c3 af op de console.
  25. Einde van de hoofdtekst van de functie main().

Runtime polymorfisme

Dit gebeurt wanneer de methode van een object wordt aangeroepen/aangeroepen tijdens runtime in plaats van tijdens het compileren. Runtime-polymorfisme wordt bereikt door het overschrijven van functies. De aan te roepen/aanroepende functie wordt tijdens runtime tot stand gebracht.

Functie overschrijven

Het overschrijven van functies vindt plaats wanneer een functie van de basisklasse een nieuwe definitie krijgt in een afgeleide klasse. Op dat moment kunnen we zeggen dat de basisfunctie is overschreven.

Bijvoorbeeld:

#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;

}

Output:

Functie overschrijven

Hier is een screenshot van de code:

Functie overschrijven

Code Verklaring:

  1. Importeer het iostream-headerbestand in ons programma om de functies ervan te gebruiken.
  2. Neem de std-naamruimte op in ons programma om de klassen ervan te gebruiken zonder deze aan te roepen.
  3. Maak een klasse met de naam Mammal. De { markeert het begin van de hoofdtekst van de klasse.
  4. Gebruik de modifier voor openbare toegang om de functie die we gaan maken in te stellen als openbaar toegankelijk. Het is toegankelijk van buiten deze les.
  5. Creëer een publieke functie met de naam eten. De { markeert het begin van de functietekst.
  6. Druk de instructie af die aan de cout-functie is toegevoegd wanneer de functie eat() wordt aangeroepen.
  7. Het einde van de hoofdtekst van de functie eat().
  8. Einde van het lichaam van de klasse Zoogdier.
  9. Maak een klasse met de naam Cow die de klasse Mammal erft. Koe is de afgeleide klasse, terwijl Zoogdier de basisklasse is. De { markeert het begin van deze klasse.
  10. Gebruik de modifier voor openbare toegang om de functie die we gaan maken als openbaar toegankelijk te markeren. Het is toegankelijk van buiten deze les.
  11. Overschrijf de functie eat() die in de basisklasse is gedefinieerd. De { markeert het begin van de functietekst.
  12. De instructie die op de console moet worden afgedrukt wanneer deze functie wordt aangeroepen.
  13. Einde van de hoofdtekst van de functie eat().
  14. Einde van het lichaam van de klasse Koe.
  15. Roep de functie main() aan. De { markeert het begin van de hoofdtekst van deze functie.
  16. Maak een instantie van de klasse Cow en geef deze de naam c.
  17. Roep de functie eat() aan die is gedefinieerd in de klasse Cow.
  18. Het programma moet bij succesvolle voltooiing een waarde retourneren.
  19. Einde van de functie main().

C++ virtuele functie

Een virtuele functie is een andere manier om runtime-polymorfisme in C++ te implementeren. Het is een speciale functie die is gedefinieerd in een basisklasse en opnieuw is gedefinieerd in de afgeleide klasse. Om een ​​virtuele functie te declareren, moet u het virtuele sleutelwoord gebruiken. Het sleutelwoord moet voorafgaan aan de declaratie van de functie in de basisklasse.

Als een virtuele functieklasse wordt geërfd, herdefinieert de virtuele klasse de virtuele functie om aan zijn behoeften te voldoen. Bijvoorbeeld:

#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();      
	}

Output:

C++ virtuele functie

Hier is een screenshot van de code:

C++ virtuele functie

Code Verklaring:

  1. Neem het iostream-headerbestand op in de code om de functies ervan te gebruiken.
  2. Neem de std-naamruimte op in onze code om de klassen ervan te gebruiken zonder deze aan te roepen.
  3. Maak een klasse met de naam ClassA.
  4. Gebruik de modifier voor openbare toegang om een ​​klaslid als openbaar toegankelijk te markeren.
  5. Maak een virtuele functie met de naam show(). Het zal een publieke functie zijn.
  6. De tekst die moet worden afgedrukt wanneer de show() wordt aangeroepen, wordt aangeroepen. De endl is een C++-sleutelwoord, wat eindregel betekent. Het verplaatst de muiscursor naar de volgende regel.
  7. Einde van de hoofdtekst van de virtuele functie show().
  8. Einde van het lichaam van de klasse Klasse A.
  9. Een nieuwe klasse maken met de naam ClassB die de klasse ClassA erft. KlasseA wordt de basisklasse, terwijl KlasseB de afgeleide klasse wordt.
  10. Gebruik de modifier voor openbare toegang om een ​​klaslid als openbaar toegankelijk te markeren.
  11. Herdefinieer de virtuele functie show() die is afgeleid in de basisklasse.
  12. De tekst die op de console moet worden afgedrukt wanneer de functie show() die in de afgeleide klasse is gedefinieerd, wordt aangeroepen.
  13. Einde van de hoofdtekst van de functie show().
  14. Einde van de hoofdtekst van de afgeleide klasse, Klasse B.
  15. Roep de functie main() aan. De programmalogica moet in de hoofdtekst worden toegevoegd.
  16. Maak een pointervariabele met de naam a. Het verwijst naar de klasse genaamd ClassA.
  17. Maak een exemplaar van de klasse met de naam ClassB. De instantie krijgt de naam b.
  18. Wijs de waardenopslagplaatsen in het adres b toe in de variabele a.
  19. Roep de functie show() aan die is gedefinieerd in de afgeleide klasse. Er is een late binding geïmplementeerd.
  20. Einde van de hoofdtekst van de functie main().

Compile-time polymorfisme versus. Runtime-polymorfisme

Dit zijn de belangrijkste verschillen tussen de twee:

Compilatietijd polymorfisme Runtime polymorfisme
Het wordt ook vroege binding of statisch polymorfisme genoemd Het wordt ook wel late/dynamische binding of dynamisch polymorfisme genoemd
De methode wordt aangeroepen/aangeroepen tijdens het compileren De methode wordt tijdens runtime aangeroepen/aangeroepen
Geïmplementeerd via functieoverbelasting en operaof overbelasting Geïmplementeerd via methodeoverschrijving en virtuele functies
Voorbeeld: overbelasting van de methode. Veel methoden kunnen vergelijkbare namen hebben, maar een verschillend aantal of verschillende soorten argumenten Voorbeeld: methode overschrijven. Veel methoden kunnen een vergelijkbare naam en hetzelfde prototype hebben.
Snellere uitvoering omdat de detectie van de methoden plaatsvindt tijdens het compileren Langzamere uitvoering omdat de methode-ontdekker tijdens runtime wordt uitgevoerd.
Er wordt minder flexibiliteit bij het oplossen van problemen geboden, omdat alles bekend is tijdens het compileren. Er is veel flexibiliteit geboden bij het oplossen van complex problemen omdat methoden tijdens runtime worden ontdekt.

Samengevat

  • Polymorfisme betekent dat je vele vormen hebt.
  • Het komt voor wanneer er een hiërarchie van klassen bestaat die verband houden via overerving.
  • Met polymorfisme kan een functie zich anders gedragen op basis van het object dat deze aanroept/aanroept.
  • Bij polymorfisme tijdens het compileren wordt de aan te roepen functie vastgesteld tijdens het compileren.
  • Bij runtime-polymorfisme wordt de aan te roepen functie tijdens runtime tot stand gebracht.
  • Compile-time polymorfisme wordt bepaald door overbelasting van functies en operaof overbelasting.
  • Bij overbelasting van functies zijn er veel functies met vergelijkbare namen maar met verschillende argumenten.
  • De parameters kunnen verschillen in aantal of type.
  • In operaVoor overbelasting wordt een nieuwe betekenis gedefinieerd C + + operaverdraaid.
  • Runtime-polymorfisme wordt bereikt door het overschrijven van functies.
  • Bij het overschrijven van functies geeft een afgeleide klasse een nieuwe definitie aan een functie die in de basisklasse is gedefinieerd.