C++ Polymorfisme met voorbeeld
Waar zit polymorfisme in? C++?
In C++zorgt polymorfisme ervoor dat een lidfunctie zich anders gedraagt op basis 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.
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.
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 de C++ compiler selecteert de juiste functie tijdens het compileren.
Polymorfisme tijdens compilatietijd wordt bereikt door functieoverbelasting en operatoroverbelasting.
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:
Hier is een screenshot van de code:
Code Verklaring:
- Neem het iostream-headerbestand op in onze code. We zullen de functies ervan kunnen gebruiken.
- Neem de std-naamruimte op in onze code. We kunnen de klassen ervan gebruiken zonder deze aan te roepen.
- 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.
- Verklaring die moet worden uitgevoerd als de bovenstaande functietest wordt aangeroepen/aangeroepen.
- Einde van de hoofdtekst van bovenstaande functietest.
- 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.
- Verklaring die moet worden uitgevoerd als de bovenstaande functietest wordt aangeroepen/aangeroepen.
- Einde van de hoofdtekst van de bovenstaande functietest.
- Maak een functie met de naam test waaraan een tekenparameter ch moet doorgegeven worden. De { markeert het begin van de hoofdtekst van de functietest.
- Verklaring die moet worden uitgevoerd als de bovenstaande functietest wordt aangeroepen/aangeroepen.
- Einde van de hoofdtekst van de bovenstaande functietest.
- Roep de functie main() aan. De { markeert het begin van de hoofdtekst van de functie.
- 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.
- 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.
- 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.
- Het programma moet een waarde retourneren als het succesvol wordt uitgevoerd.
- 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 a C++ operator. Het verandert ook hoe de operator werkt. We kunnen bijvoorbeeld de + operator definiëren om twee strings aan elkaar te koppelen. We kennen het als de opteloperator voor het optellen van numerieke waarden. Na onze definitie, wanneer geplaatst tussen gehele getallen, zal het ze optellen. Wanneer geplaatst tussen strings, zal het ze aan elkaar koppelen.
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:
Hier is een screenshot van de code:
Code Verklaring:
- Voeg het iostream-headerbestand toe aan ons programma om de functies ervan te kunnen gebruiken.
- Neem de std-naamruimte op in ons programma om de klassen ervan te gebruiken zonder deze aan te roepen.
- Maak een klasse genaamd ComplexNum. De { markeert het begin van de klassebody.
- Gebruik de private access modifier om variabelen als privé te markeren, wat betekent dat ze alleen toegankelijk zijn vanuit de klasse.
- Definieer twee integer-variabelen, real en over.
- Gebruik de public access modifier om de constructor als openbaar te markeren, wat betekent dat deze zelfs van buitenaf toegankelijk is klasse.
- Maak de klassenconstructor en initialiseer de variabelen.
- Initialiseer de waarde van de variabele real.
- Initialiseer de waarde van de variabele over.
- Einde van het constructorlichaam.
- We moeten de betekenis van de + operator overschrijven.
- Maak het gegevenstyperesultaat van het type ComplexNum.
- Gebruik de + operator met complexe getallen. Deze regel telt het reële deel van een getal op bij het reële deel van een ander getal.
- Gebruik de + operator met complexe getallen. Deze regel telt het imaginaire deel van een getal op bij het imaginaire deel van een ander getal.
- Het programma retourneert de waarde van het variabele resultaat bij succesvolle uitvoering.
- Einde van de definitie van de nieuwe betekenis van de + operator, namelijk overbelasting.
- Roep de methode print() aan.
- Druk het nieuwe complexe getal af na optelling op de console.
- Einde van de hoofdtekst van de functie print().
- Einde van de hoofdtekst van de klasse ComplexNum.
- Roep de functie main() aan.
- Geef de waarden van zowel de reële als de complexe delen door die moeten worden opgeteld. Het eerste deel van c1 wordt opgeteld bij 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.
- Voer een bewerking uit met behulp van de overbelaste + operator en sla het resultaat op in variabele c3.
- Druk de waarde van variabele c3 af op de console.
- 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:
Hier is een screenshot van de code:
Code Verklaring:
- Importeer het iostream-headerbestand in ons programma om de functies ervan te gebruiken.
- Neem de std-naamruimte op in ons programma om de klassen ervan te gebruiken zonder deze aan te roepen.
- Maak een klasse met de naam Mammal. De { markeert het begin van de hoofdtekst van de klasse.
- 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.
- Creëer een publieke functie met de naam eten. De { markeert het begin van de functietekst.
- Druk de instructie af die aan de cout-functie is toegevoegd wanneer de functie eat() wordt aangeroepen.
- Het einde van de hoofdtekst van de functie eat().
- Einde van het lichaam van de klasse Zoogdier.
- 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.
- 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.
- Overschrijf de functie eat() die in de basisklasse is gedefinieerd. De { markeert het begin van de functietekst.
- De instructie die op de console moet worden afgedrukt wanneer deze functie wordt aangeroepen.
- Einde van de hoofdtekst van de functie eat().
- Einde van het lichaam van de klasse Koe.
- Roep de functie main() aan. De { markeert het begin van de hoofdtekst van deze functie.
- Maak een instantie van de klasse Cow en geef deze de naam c.
- Roep de functie eat() aan die is gedefinieerd in de klasse Cow.
- Het programma moet bij succesvolle voltooiing een waarde retourneren.
- Einde van de functie main().
C++ Virtuele functie
Een virtuele functie is een andere manier om runtime-polymorfisme te implementeren in C++. 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:
Hier is een screenshot van de code:
Code Verklaring:
- Neem het iostream-headerbestand op in de code om de functies ervan te gebruiken.
- Neem de std-naamruimte op in onze code om de klassen ervan te gebruiken zonder deze aan te roepen.
- Maak een klasse met de naam ClassA.
- Gebruik de modifier voor openbare toegang om een klaslid als openbaar toegankelijk te markeren.
- Maak een virtuele functie met de naam show(). Het zal een publieke functie zijn.
- De tekst die moet worden afgedrukt wanneer de show() wordt aangeroepen, wordt aangeroepen. Het einde is een C++ trefwoord, wat eindregel betekent. Het verplaatst de muiscursor naar de volgende regel.
- Einde van de hoofdtekst van de virtuele functie show().
- Einde van het lichaam van de klasse Klasse A.
- Een nieuwe klasse maken met de naam ClassB die de klasse ClassA erft. KlasseA wordt de basisklasse, terwijl KlasseB de afgeleide klasse wordt.
- Gebruik de modifier voor openbare toegang om een klaslid als openbaar toegankelijk te markeren.
- Herdefinieer de virtuele functie show() die is afgeleid in de basisklasse.
- De tekst die op de console moet worden afgedrukt wanneer de functie show() die in de afgeleide klasse is gedefinieerd, wordt aangeroepen.
- Einde van de hoofdtekst van de functie show().
- Einde van de hoofdtekst van de afgeleide klasse, Klasse B.
- Roep de functie main() aan. De programmalogica moet in de hoofdtekst worden toegevoegd.
- Maak een pointervariabele met de naam a. Het verwijst naar de klasse genaamd ClassA.
- Maak een exemplaar van de klasse met de naam ClassB. De instantie krijgt de naam b.
- Wijs de waardenopslagplaatsen in het adres b toe in de variabele a.
- Roep de functie show() aan die is gedefinieerd in de afgeleide klasse. Er is een late binding geïmplementeerd.
- 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 functie-overbelasting en operator-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. |
Less Er wordt flexibiliteit bij het oplossen van problemen geboden, omdat alles bekend is tijdens het compileren. | Er is veel flexibiliteit voor het oplossen van complexe problemen, omdat methoden tijdens runtime worden ontdekt. |
Samenvatting
- 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.
- Polymorfisme tijdens compilatie wordt bepaald door functieoverbelasting en operatoroverbelasting.
- Bij overbelasting van functies zijn er veel functies met vergelijkbare namen maar met verschillende argumenten.
- De parameters kunnen verschillen in aantal of type.
- Bij operator overloading wordt een nieuwe betekenis gedefinieerd voor C++ exploitanten.
- 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.