C++ Polymorfisme med eksempel
โก Smart oppsummering
Polymorfisme i C++ lar en enkeltmedlemsfunksjon ta mange former, og oppfรธre seg forskjellig avhengig av objektet som pรฅkaller den. Den bygger pรฅ arv og vises i to varianter, lรธst enten ved kompileringstid eller kjรธretid.

Hva er polymorfisme i C++?
In C++, polymorfisme fรธrer til at en medlemsfunksjon oppfรธrer seg annerledes basert pรฅ objektet som kaller/pรฅkaller den. Polymorfisme er et gresk ord som betyr รฅ ha mange former. Det oppstรฅr nรฅr du har et hierarki av klasser beslektet gjennom arv.
Anta for eksempel at vi har funksjonen makeSound(). Nรฅr en katt kaller denne funksjonen, vil den produsere mjau-lyden. Nรฅr en ku pรฅkaller den samme funksjonen, vil den gi klippelyden.
Selv om vi har รฉn funksjon, oppfรธrer den seg annerledes under forskjellige omstendigheter. Funksjonen har mange former; derfor har vi oppnรฅdd polymorfisme.
Med kjerneideen pรฅ plass, C++ organiserer denne oppfรธrselen i to forskjellige kategorier.
Typer polymorfisme
C++ stรธtter to typer polymorfisme:
- Kompileringstidspolymorfisme, og
- Runtime polymorfisme.
Den fรธrste kategorien lรธser alle funksjonskall fรธr programmet i det hele tatt kjรธrer.
Kompiler tidspolymorfisme
Du pรฅkaller de overbelastede funksjonene ved รฅ matche antall og type argumenter. Informasjonen er tilstede under kompileringstiden. Dette betyr C++ kompilatoren vil velge riktig funksjon pรฅ kompileringstidspunktet.
Kompileringstidspolymorfisme oppnรฅs gjennom funksjonsoverbelastning og operatรธroverbelastning.
Funksjon Overbelastning
Funksjonsoverbelastning oppstรฅr nรฅr vi har mange funksjoner med like navn, men forskjellige argumenter. Argumentene kan variere nรฅr det gjelder antall eller type.
Eksempel 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; }
Utgang:
Her er et skjermbilde av koden:
Code Forklaring:
- Inkluder iostream-headerfilen i koden vรฅr. Vi vil kunne bruke funksjonene.
- Inkluder std-navneomrรฅdet i koden vรฅr. Vi vil kunne bruke klassene uten รฅ ringe det.
- Opprett en funksjon kalt test som tar en heltallsparameter i. { markerer begynnelsen pรฅ funksjonstesten.
- Uttalelse som skal utfรธres hvis funksjonstesten ovenfor pรฅkalles/kalles.
- Slutten av hoveddelen av funksjonstesten ovenfor.
- Opprett en funksjon kalt test som tar en flytparameter f. { markerer begynnelsen pรฅ funksjonstesten.
- Uttalelse som skal utfรธres hvis funksjonstesten ovenfor pรฅkalles/kalles.
- Slutten av hoveddelen av funksjonstesten ovenfor.
- Lag en funksjon kalt test som tar en tegnparameter ch. { markerer begynnelsen pรฅ funksjonstesten.
- Uttalelse som skal utfรธres hvis funksjonstesten ovenfor pรฅkalles/kalles.
- Slutten av hoveddelen av funksjonstesten ovenfor.
- Kalle hoved()-funksjonen. { markerer begynnelsen pรฅ kroppen til funksjonen.
- Ring funksjonstesten og send 5 til den som verdien av argumentet. Dette pรฅkaller testfunksjonen som godtar et heltallsargument, det vil si den fรธrste testfunksjonen.
- Kall funksjonstesten og send 5.5 til den som verdien av argumentet. Dette vil pรฅkalle testfunksjonen som godtar et flytargument, det vil si den andre testfunksjonen.
- Ring funksjonstesten og send fem til den som verdien av argumentet. Dette vil pรฅkalle testfunksjonen som godtar et tegnargument, det vil si den tredje testfunksjonen.
- Programmet mรฅ returnere en verdi hvis det kjรธrer vellykket.
- Slutten av hoveddelen av hoved()-funksjonen.
Vi har tre funksjoner med samme navn, men forskjellige typer argumenter. Vi har oppnรฅdd polymorfisme.
Operator overbelastning
In Operafor overbelastning, definerer vi en ny betydning for en C++ operatรธr. Det endrer ogsรฅ hvordan operatoren fungerer. For eksempel kan vi definere + -operatoren for รฅ sammenkoble to strenger. Vi kjenner den som addisjonsoperatoren for รฅ legge sammen numeriske verdier. Etter vรฅr definisjon, nรฅr den plasseres mellom heltall, vil den legge dem sammen. Nรฅr den plasseres mellom strenger, vil den sammenkoble dem.
Eksempel 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(); }
Utgang:
Her er et skjermbilde av koden:
Code Forklaring:
- Inkluder iostream-headerfilen i programmet vรฅrt for รฅ bruke funksjonene.
- Inkluder std-navneomrรฅdet i programmet vรฅrt for รฅ bruke klassene uten รฅ kalle det.
- Lag en klasse som heter ComplexNum. { markerer begynnelsen pรฅ klasseteksten.
- Bruk modifikatoren for privat tilgang til รฅ merke variabler som private, noe som betyr at de kun kan nรฅs fra klassen.
- Definer to heltallsvariabler, reelle og over.
- Bruk modifikatoren for offentlig tilgang til รฅ markere konstruktรธren som offentlig, som betyr at den vil vรฆre tilgjengelig selv utenfra klassen.
- Lag klassekonstruktรธren og initialiser variablene.
- Initialiser verdien av variabelen reell.
- Initialiser verdien av variabelen over.
- Slutten av konstruktรธrkroppen.
- Vi mรฅ overstyre betydningen av +-operatoren.
- Opprett datatyperesultatet av typen ComplexNum.
- Bruk operatoren + med komplekse tall. Denne linjen vil legge til den reelle delen av et tall til den reelle delen av et annet tall.
- Bruk operatoren + med komplekse tall. Denne linjen vil legge til den imaginรฆre delen av et tall til den imaginรฆre delen av et annet tall.
- Programmet vil returnere verdien av variabelresultatet ved vellykket utfรธrelse.
- Slutten av definisjonen av den nye betydningen av + operatรธr, det vil si overbelastning.
- Kall opp print()-metoden.
- Skriv ut det nye komplekse tallet etter addisjon pรฅ konsollen.
- Slutten av hovedteksten () funksjon.
- Slutten av brรธdteksten til ComplexNum-klassen.
- Kalle hoved()-funksjonen.
- Send verdiene til bรฅde reelle og komplekse deler som skal legges til. Den fรธrste delen av c1 vil bli lagt til den fรธrste delen av c2, det vil si 10+3. Den andre delen av c1 vil bli lagt til den andre delen av c, det vil si 2+7.
- Utfรธr en operasjon ved รฅ bruke overbelastet +-operatoren og lagre resultatet i variabel c3.
- Skriv ut verdien av variabel c3 pรฅ konsollen.
- Slutten av hoveddelen av funksjonen main().
Der polymorfisme ved kompilering avgjรธr tidlig, utsetter den andre kategorien valget til utfรธrelse.
Runtime polymorfisme
Dette skjer nรฅr et objekts metode pรฅkalles/kalles under kjรธring i stedet for under kompileringstiden. Runtime polymorfisme oppnรฅs gjennom funksjonsoverstyring. Funksjonen som skal kalles/pรฅkalles etableres under kjรธring.
Funksjonsoverstyring
Funksjonsoverstyring skjer nรฅr en funksjon av basisklassen fรฅr en ny definisjon i en avledet klasse. Pรฅ det tidspunktet kan vi si at basisfunksjonen har blitt overstyrt.
For eksempel:
#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; }
Utgang:
Her er et skjermbilde av koden:
Code Forklaring:
- Importer iostream-headerfilen til programmet vรฅrt for รฅ bruke funksjonene.
- Inkluder std-navneomrรฅdet i programmet vรฅrt for รฅ bruke klassene uten รฅ kalle det.
- Lag en klasse som heter Mammal. { markerer begynnelsen av klasseteksten.
- Bruk modifikatoren for offentlig tilgang til รฅ angi funksjonen vi skal lage som offentlig tilgjengelig. Den vil vรฆre tilgjengelig utenfor denne klassen.
- Lag en offentlig funksjon som heter eat. { markerer begynnelsen av funksjonsteksten.
- Skriv ut setningen som er lagt til cout-funksjonen nรฅr funksjonen eat() pรฅkalles.
- Slutten av funksjonskroppen spise().
- Slutten av kroppen til klassen Pattedyr.
- Lag en klasse som heter Cow som arver pattedyrklassen. Ku er den avledede klassen, mens pattedyr er basisklassen. { markerer begynnelsen pรฅ denne klassen.
- Bruk modifikatoren for offentlig tilgang til รฅ merke funksjonen vi er i ferd med รฅ lage som offentlig tilgjengelig. Den vil vรฆre tilgjengelig utenfor denne klassen.
- Overstyr funksjonen eat() som ble definert i basisklassen. { markerer begynnelsen av funksjonsteksten.
- Uttalelsen som skal skrives ut pรฅ konsollen nรฅr denne funksjonen aktiveres.
- Slutten av kroppen av funksjonen eat().
- Slutten av kroppen til klassen Ku.
- Kalle hoved()-funksjonen. { markerer begynnelsen pรฅ hoveddelen av denne funksjonen.
- Lag en forekomst av Cow-klassen og gi den navnet c.
- Kall eat()-funksjonen definert i Cow-klassen.
- Programmet mรฅ returnere en verdi ved vellykket gjennomfรธring.
- Slutten av hoved()-funksjonen.
C++ Virtuell funksjon
En virtuell funksjon er en annen mรฅte รฅ implementere run-time polymorfisme i C++. Det er en spesiell funksjon definert i en basisklasse og redefinert i den avledede klassen. For รฅ erklรฆre en virtuell funksjon, bรธr du bruke det virtuelle nรธkkelordet. Nรธkkelordet skal gรฅ foran deklarasjonen av funksjonen i basisklassen.
Hvis en virtuell funksjonsklasse er arvet, redefinerer den virtuelle klassen den virtuelle funksjonen for รฅ passe dens behov. For eksempel:
#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(); }
Utgang:
Her er et skjermbilde av koden:
Code Forklaring:
- Inkluder iostream-headerfilen i koden for รฅ bruke funksjonene.
- Inkluder std-navneomrรฅdet i koden vรฅr for รฅ bruke klassene uten รฅ kalle det.
- Lag en klasse som heter ClassA.
- Bruk modifikatoren for offentlig tilgang til รฅ merke et klassemedlem som offentlig tilgjengelig.
- Lag en virtuell funksjon kalt show(). Det blir en offentlig funksjon.
- Teksten som skal skrives ut nรฅr show() pรฅkalles, pรฅkalles. Endl er en C++ nรธkkelord, som betyr sluttlinje. Den flytter musepekeren til neste linje.
- Slutten av kroppen til den virtuelle funksjonen show().
- Slutten av brรธdteksten til klassen KlasseA.
- Opprette en ny klasse kalt ClassB som arver klassen ClassA. KlasseA blir basisklassen mens KlasseB blir den avledede klassen.
- Bruk modifikatoren for offentlig tilgang til รฅ merke et klassemedlem som offentlig tilgjengelig.
- Redefiner den virtuelle funksjonen show() utledet i basisklassen.
- Teksten som skal skrives ut pรฅ konsollen nรฅr show()-funksjonen definert i den avledede klassen pรฅkalles.
- Slutten av brรธdteksten til show()-funksjonen.
- Slutten av kroppen til den avledede klassen, KlasseB.
- Kalle hoved()-funksjonen. Programlogikken bรธr legges til i hoveddelen.
- Lag en pekervariabel kalt a. Den peker pรฅ klassen som heter ClassA.
- Opprett en forekomst av klassen kalt ClassB. Forekomsten fรฅr navnet b.
- Tilordne verdiene lagres i adressen b i variabelen a.
- Pรฅkall show()-funksjonen definert i den avledede klassen. Sen binding er iverksatt.
- Slutten av hoveddelen av hoved()-funksjonen.
Tabellen nedenfor viser begge mekanismene side om side, og de er dekket.
Kompileringstidspolymorfisme vs. Run-Time Polymorphism
Her er de viktigste forskjellene mellom de to:
| Kompileringstidspolymorfisme | Run-time polymorfisme |
|---|---|
| Det kalles ogsรฅ tidlig binding eller statisk polymorfisme | Det kalles ogsรฅ sen/dynamisk binding eller dynamisk polymorfisme |
| Metoden kalles/pรฅkalles under kompileringstiden | Metoden kalles/pรฅkalles under kjรธretid |
| Implementert via funksjonsoverbelastning og operatรธroverbelastning | Implementert via metodeoverstyring og virtuelle funksjoner |
| Eksempel, metodeoverbelastning. Mange metoder kan ha lignende navn, men forskjellige antall eller typer argumenter | Eksempel, metodeoverstyring. Mange metoder kan ha et lignende navn og samme prototype. |
| Raskere utfรธrelse siden metodeoppdagelsen gjรธres under kompileringstiden | Tregere utfรธrelse siden metodeoppdagelse gjรธres under kjรธretid. |
| Less fleksibilitet for problemlรธsning er gitt siden alt er kjent under kompileringstiden. | Mye fleksibilitet er gitt for รฅ lรธse komplekse problemer siden metoder oppdages under kjรธring. |







