C++ Polymorfisme med eksempel

Hva er polymorfisme i C++?

In C++, forårsaker polymorfisme 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 relatert 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.

Polymorfisme i C++

Selv om vi har én funksjon, oppfører den seg annerledes under forskjellige omstendigheter. Funksjonen har mange former; derfor har vi oppnådd polymorfisme.

Typer polymorfisme

C++ støtter to typer polymorfisme:

  • Kompileringstidspolymorfisme, og
  • Runtime polymorfisme.

Typer polymorfisme

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:

Funksjon Overbelastning

Her er et skjermbilde av koden:

Funksjon Overbelastning

Kodeforklaring:

  1. Inkluder iostream-headerfilen i koden vår. Vi vil kunne bruke funksjonene.
  2. Inkluder std-navneområdet i koden vår. Vi vil kunne bruke klassene uten å ringe det.
  3. Opprett en funksjon kalt test som tar en heltallsparameter i. { markerer begynnelsen på funksjonstesten.
  4. Uttalelse som skal utføres hvis funksjonstesten ovenfor påkalles/kalles.
  5. Slutten av hoveddelen av funksjonstesten ovenfor.
  6. Opprett en funksjon kalt test som tar en flytparameter f. { markerer begynnelsen på funksjonstesten.
  7. Uttalelse som skal utføres hvis funksjonstesten ovenfor påkalles/kalles.
  8. Slutten av hoveddelen av funksjonstesten ovenfor.
  9. Lag en funksjon kalt test som tar en tegnparameter ch. { markerer begynnelsen på funksjonstesten.
  10. Uttalelse som skal utføres hvis funksjonstesten ovenfor påkalles/kalles.
  11. Slutten av hoveddelen av funksjonstesten ovenfor.
  12. Kalle hoved()-funksjonen. { markerer begynnelsen på kroppen til funksjonen.
  13. 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.
  14. 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.
  15. 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.
  16. Programmet må returnere en verdi hvis det kjører vellykket.
  17. 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 operatøren fungerer. For eksempel kan vi definere +-operatoren for å sette sammen to strenger. Vi kjenner det som addisjonsoperatoren for å legge til numeriske verdier. Etter vår definisjon, når den plasseres mellom heltall, vil den legge dem til. Når den plasseres mellom strenger, vil den sette dem sammen.

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:

Operator overbelastning

Her er et skjermbilde av koden:

Operator overbelastning

Operator overbelastning

Kodeforklaring:

  1. Inkluder iostream-headerfilen i programmet vårt for å bruke funksjonene.
  2. Inkluder std-navneområdet i programmet vårt for å bruke klassene uten å kalle det.
  3. Lag en klasse som heter ComplexNum. { markerer begynnelsen på klasseteksten.
  4. Bruk modifikatoren for privat tilgang til å merke variabler som private, noe som betyr at de kun kan nås fra klassen.
  5. Definer to heltallsvariabler, reelle og over.
  6. Bruk modifikatoren for offentlig tilgang til å merke konstruktøren som offentlig, noe som betyr at den vil være tilgjengelig selv fra utenfor klasse.
  7. Lag klassekonstruktøren og initialiser variablene.
  8. Initialiser verdien av variabelen reell.
  9. Initialiser verdien av variabelen over.
  10. Slutten av konstruktørkroppen.
  11. Vi må overstyre betydningen av +-operatoren.
  12. Opprett datatyperesultatet av typen ComplexNum.
  13. Bruk operatoren + med komplekse tall. Denne linjen vil legge til den reelle delen av et tall til den reelle delen av et annet tall.
  14. 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.
  15. Programmet vil returnere verdien av variabelresultatet ved vellykket utførelse.
  16. Slutten av definisjonen av den nye betydningen av + operatør, det vil si overbelastning.
  17. Kall opp print()-metoden.
  18. Skriv ut det nye komplekse tallet etter addisjon på konsollen.
  19. Slutten av hovedteksten () funksjon.
  20. Slutten av brødteksten til ComplexNum-klassen.
  21. Kalle hoved()-funksjonen.
  22. 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.
  23. Utfør en operasjon ved å bruke overbelastet +-operatoren og lagre resultatet i variabel c3.
  24. Skriv ut verdien av variabel c3 på konsollen.
  25. Slutten av hoveddelen av funksjonen main().

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:

Funksjonsoverstyring

Her er et skjermbilde av koden:

Funksjonsoverstyring

Kodeforklaring:

  1. Importer iostream-headerfilen til programmet vårt for å bruke funksjonene.
  2. Inkluder std-navneområdet i programmet vårt for å bruke klassene uten å kalle det.
  3. Lag en klasse som heter Mammal. { markerer begynnelsen av klasseteksten.
  4. Bruk modifikatoren for offentlig tilgang til å angi funksjonen vi skal lage som offentlig tilgjengelig. Den vil være tilgjengelig utenfor denne klassen.
  5. Lag en offentlig funksjon som heter eat. { markerer begynnelsen av funksjonsteksten.
  6. Skriv ut setningen som er lagt til cout-funksjonen når funksjonen eat() påkalles.
  7. Slutten av funksjonskroppen spise().
  8. Slutten av kroppen til klassen Pattedyr.
  9. Lag en klasse som heter Cow som arver pattedyrklassen. Ku er den avledede klassen, mens pattedyr er basisklassen. { markerer begynnelsen på denne klassen.
  10. 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.
  11. Overstyr funksjonen eat() som ble definert i basisklassen. { markerer begynnelsen av funksjonsteksten.
  12. Uttalelsen som skal skrives ut på konsollen når denne funksjonen aktiveres.
  13. Slutten av kroppen av funksjonen eat().
  14. Slutten av kroppen til klassen Ku.
  15. Kalle hoved()-funksjonen. { markerer begynnelsen på hoveddelen av denne funksjonen.
  16. Lag en forekomst av Cow-klassen og gi den navnet c.
  17. Kall eat()-funksjonen definert i Cow-klassen.
  18. Programmet må returnere en verdi ved vellykket gjennomføring.
  19. 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:

C++ Virtuell funksjon

Her er et skjermbilde av koden:

C++ Virtuell funksjon

Kodeforklaring:

  1. Inkluder iostream-headerfilen i koden for å bruke funksjonene.
  2. Inkluder std-navneområdet i koden vår for å bruke klassene uten å kalle det.
  3. Lag en klasse som heter ClassA.
  4. Bruk modifikatoren for offentlig tilgang til å merke et klassemedlem som offentlig tilgjengelig.
  5. Lag en virtuell funksjon kalt show(). Det blir en offentlig funksjon.
  6. 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.
  7. Slutten av kroppen til den virtuelle funksjonen show().
  8. Slutten av brødteksten til klassen KlasseA.
  9. Opprette en ny klasse kalt ClassB som arver klassen ClassA. KlasseA blir basisklassen mens KlasseB blir den avledede klassen.
  10. Bruk modifikatoren for offentlig tilgang til å merke et klassemedlem som offentlig tilgjengelig.
  11. Redefiner den virtuelle funksjonen show() utledet i basisklassen.
  12. Teksten som skal skrives ut på konsollen når show()-funksjonen definert i den avledede klassen påkalles.
  13. Slutten av brødteksten til show()-funksjonen.
  14. Slutten av kroppen til den avledede klassen, KlasseB.
  15. Kalle hoved()-funksjonen. Programlogikken bør legges til i hoveddelen.
  16. Lag en pekervariabel kalt a. Den peker på klassen som heter ClassA.
  17. Opprett en forekomst av klassen kalt ClassB. Forekomsten får navnet b.
  18. Tilordne verdiene lagres i adressen b i variabelen a.
  19. Påkall show()-funksjonen definert i den avledede klassen. Sen binding er iverksatt.
  20. Slutten av hoveddelen av hoved()-funksjonen.

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 i kompileringstiden Langsommere kjøring siden metodeoppdager gjøres under kjøring.
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.

Sammendrag

  • Polymorfisme betyr å ha mange former.
  • Det oppstår når det er et hierarki av klasser relatert gjennom arv.
  • Med polymorfisme kan en funksjon oppføre seg annerledes basert på objektet som påkaller/kaller den.
  • I kompileringstidspolymorfisme etableres funksjonen som skal påkalles under kompileringstiden.
  • I kjøretidspolymorfisme etableres funksjonen som skal påkalles under kjøretid.
  • Kompileringstidspolymorfisme bestemmes gjennom funksjonsoverbelastning og operatøroverbelastning.
  • Ved funksjonsoverbelastning er det mange funksjoner med lignende navn, men forskjellige argumenter.
  • Parametrene kan variere i antall eller type.
  • Ved operatøroverbelastning defineres en ny betydning for C++ operatører.
  • Runtime polymorfisme oppnås gjennom funksjonsoverstyring.
  • Ved funksjonsoverstyring gir en avledet klasse en ny definisjon til en funksjon definert i basisklassen.