C++ Polymorfism med exempel
Vad รคr polymorfism i C++?
In C++, gรถr polymorfism att en medlemsfunktion beter sig annorlunda baserat pรฅ objektet som anropar/anropar den. Polymorfism รคr ett grekiskt ord som betyder att ha mรฅnga former. Det intrรคffar nรคr du har en hierarki av klasser relaterade genom arv.
Anta till exempel att vi har funktionen makeSound(). Nรคr en katt anropar denna funktion kommer den att producera ett mjauljud. Nรคr en ko รฅberopar samma funktion, kommer den att ge klippljudet.
รven om vi har en funktion, beter sig den olika under olika omstรคndigheter. Funktionen har mรฅnga former; dรคrfรถr har vi uppnรฅtt polymorfism.
Typer av polymorfism
C++ stรถder tvรฅ typer av polymorfism:
- Kompileringstidspolymorfism, och
- Runtime polymorfism.
Kompilera tidspolymorfism
Du anropar de รถverbelastade funktionerna genom att matcha antalet och typen av argument. Informationen finns nรคrvarande under kompileringstiden. Detta betyder C++ kompilatorn vรคljer rรคtt funktion vid kompilering.
Kompileringstidspolymorfism uppnรฅs genom funktionsรถverbelastning och operatรถrsรถverbelastning.
Funktion รverbelastning
Funktionsรถverbelastning uppstรฅr nรคr vi har mรฅnga funktioner med liknande namn men olika argument. Argumenten kan skilja sig รฅt vad gรคller antal eller typ.
Exempelvis 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;
}
Produktion:
Hรคr รคr en skรคrmdump av koden:
Code Fรถrklaring:
- Inkludera iostream-huvudfilen i vรฅr kod. Vi kommer att kunna anvรคnda dess funktioner.
- Inkludera std-namnomrรฅdet i vรฅr kod. Vi kommer att kunna anvรคnda dess klasser utan att ringa det.
- Skapa en funktion med namnet test som tar en heltalsparameter i. { markerar bรถrjan av funktionstestet.
- Uttalandet som ska utfรถras om ovanstรฅende funktionsteste anropas/anropas.
- Slutet pรฅ huvuddelen av ovanstรฅende funktionstest.
- Skapa en funktion med namnet test som tar en flytparameter f. { markerar bรถrjan av funktionstestet.
- Uttalandet som ska utfรถras om ovanstรฅende funktionsteste anropas/anropas.
- Slutet pรฅ kroppen av ovanstรฅende funktionstest.
- Skapa en funktion som heter test som tar en teckenparameter ch. { markerar bรถrjan av funktionstestet.
- Uttalandet som ska utfรถras om ovanstรฅende funktionsteste anropas/anropas.
- Slutet pรฅ kroppen av ovanstรฅende funktionstest.
- Anropa main()-funktionen. { markerar bรถrjan av funktionens brรถdtext.
- Anropa funktionstestet och skicka 5 till det som vรคrdet pรฅ argumentet. Detta anropar testfunktionen som accepterar ett heltalsargument, det vill sรคga den fรถrsta testfunktionen.
- Anropa funktionstestet och skicka 5.5 till det som vรคrdet pรฅ argumentet. Detta kommer att anropa testfunktionen som accepterar ett flytargument, det vill sรคga den andra testfunktionen.
- Anropa funktionstestet och skicka fem till det som vรคrdet pรฅ argumentet. Detta kommer att anropa testfunktionen som accepterar ett teckenargument, det vill sรคga den tredje testfunktionen.
- Programmet mรฅste returnera ett vรคrde om det kรถrs framgรฅngsrikt.
- Slutet pรฅ huvuddelen av funktionen main().
Vi har tre funktioner med samma namn men olika typer av argument. Vi har uppnรฅtt polymorfism.
Operator รถverbelastning
In OperaFรถr รถverbelastning definierar vi en ny betydelse fรถr en C++ operatรถr. Det fรถrรคndrar ocksรฅ hur operatรถren arbetar. Till exempel kan vi definiera operatorn + fรถr att sammanfoga tvรฅ strรคngar. Vi kรคnner till det som additionsoperatorn fรถr att lรคgga till numeriska vรคrden. Efter vรฅr definition, nรคr den placeras mellan heltal, kommer den att lรคgga till dem. Nรคr den placeras mellan strรคngar kommer den att sammanfoga dem.
Exempelvis 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();
}
Produktion:
Hรคr รคr en skรคrmdump av koden:
Code Fรถrklaring:
- Inkludera iostream-huvudfilen i vรฅrt program fรถr att kunna anvรคnda dess funktioner.
- Inkludera std-namnomrรฅdet i vรฅrt program fรถr att kunna anvรคnda dess klasser utan att anropa det.
- Skapa en klass med namnet ComplexNum. { markerar bรถrjan av klasskroppen.
- Anvรคnd modifieraren fรถr privat รฅtkomst fรถr att markera variabler som privata, vilket innebรคr att de bara kan nรฅs frรฅn klassen.
- Definiera tvรฅ heltalsvariabler, reella och รถver.
- Anvรคnd public access-modifieraren fรถr att markera konstruktรถren som offentlig, vilket betyder att den kommer att vara tillgรคnglig รคven utanfรถr klass.
- Skapa klasskonstruktorn och initiera variablerna.
- Initiera vรคrdet pรฅ variabeln real.
- Initiera vรคrdet pรฅ variabeln รถver.
- Slutet pรฅ konstruktorkroppen.
- Vi mรฅste รฅsidosรคtta innebรถrden av +-operatorn.
- Skapa datatypresultatet av typen ComplexNum.
- Anvรคnd operatorn + med komplexa tal. Denna rad lรคgger till den reella delen av ett tal till den reella delen av ett annat tal.
- Anvรคnd operatorn + med komplexa tal. Denna linje kommer att lรคgga till den imaginรคra delen av ett tal till den imaginรคra delen av ett annat tal.
- Programmet kommer att returnera vรคrdet pรฅ variabelresultatet vid framgรฅngsrik exekvering.
- Slutet pรฅ definitionen av den nya betydelsen av + operatรถr, det vill sรคga รถverbelastning.
- Anropa metoden print().
- Skriv ut det nya komplexa numret efter tillรคgg pรฅ konsolen.
- Slutet pรฅ body of print()-funktionen.
- Slutet pรฅ brรถdtexten i klassen ComplexNum.
- Anropa main()-funktionen.
- Godkรคnn vรคrdena fรถr bรฅde verkliga och komplexa delar som ska lรคggas till. Den fรถrsta delen av c1 kommer att lรคggas till den fรถrsta delen av c2, det vill sรคga 10+3. Den andra delen av c1 kommer att lรคggas till den andra delen av c, det vill sรคga 2+7.
- Utfรถr en operation med operatorn รถverbelastad + och lagra resultatet i variabel c3.
- Skriv ut vรคrdet fรถr variabel c3 pรฅ konsolen.
- Slutet pรฅ huvuddelen av funktionen main().
Runtime polymorfism
Detta hรคnder nรคr ett objekts metod anropas/anropas under kรถrning snarare รคn under kompileringstid. Runtime polymorfism uppnรฅs genom funktionsรถverstyrning. Funktionen som ska anropas/anropas etableras under kรถrning.
Funktion ร sidosรคttande
Funktionsรถverstyrning intrรคffar nรคr en funktion av basklassen ges en ny definition i en hรคrledd klass. Vid den tiden kan vi sรคga att basfunktionen har รฅsidosatts.
Till exempel:
#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;
}
Produktion:
Hรคr รคr en skรคrmdump av koden:
Code Fรถrklaring:
- Importera iostream-huvudfilen till vรฅrt program fรถr att anvรคnda dess funktioner.
- Inkludera std-namnomrรฅdet i vรฅrt program fรถr att kunna anvรคnda dess klasser utan att anropa det.
- Skapa en klass som heter Mammal. { markerar bรถrjan av klasskroppen.
- Anvรคnd public access-modifieraren fรถr att stรคlla in funktionen vi ska skapa som allmรคnt tillgรคnglig. Den kommer att vara tillgรคnglig utanfรถr denna klass.
- Skapa en offentlig funktion som heter eat. { markerar bรถrjan av funktionskroppen.
- Skriv ut satsen som lรคggs till cout-funktionen nรคr funktionen eat() anropas.
- I slutet av kroppen av funktion eat().
- Slutet av kroppen av klassen dรคggdjur.
- Skapa en klass som heter Ko som รคrver klassen dรคggdjur. Ko รคr den hรคrledda klassen, medan dรคggdjur รคr basklassen. { markerar bรถrjan pรฅ denna klass.
- Anvรคnd public access-modifieraren fรถr att markera funktionen vi hรฅller pรฅ att skapa som allmรคnt tillgรคnglig. Den kommer att vara tillgรคnglig utanfรถr denna klass.
- ร sidosรคtt funktionen eat() som definierades i basklassen. { markerar bรถrjan av funktionskroppen.
- Uttalandet som ska skrivas ut pรฅ konsolen nรคr denna funktion anropas.
- Slutet av kroppen av funktionen eat().
- Slutet av kroppen av klassen Ko.
- Anropa main()-funktionen. { markerar bรถrjan pรฅ kroppen av denna funktion.
- Skapa en instans av Cow-klassen och ge den namnet c.
- Anropa eat()-funktionen definierad i Cow-klassen.
- Programmet mรฅste returnera ett vรคrde efter framgรฅngsrikt slutfรถrande.
- Slutet pรฅ main()-funktionen.
C++ Virtuell funktion
En virtuell funktion รคr ett annat sรคtt att implementera runtime polymorfism i C++. Det รคr en speciell funktion som definieras i en basklass och omdefinieras i den hรคrledda klassen. Fรถr att deklarera en virtuell funktion bรถr du anvรคnda det virtuella nyckelordet. Nyckelordet ska fรถregรฅ deklarationen av funktionen i basklassen.
Om en virtuell funktionsklass รคrvs, omdefinierar den virtuella funktionen den virtuella funktionen fรถr att passa dess behov. Till exempel:
#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();
}
Produktion:
Hรคr รคr en skรคrmdump av koden:
Code Fรถrklaring:
- Inkludera iostream-huvudfilen i koden fรถr att anvรคnda dess funktioner.
- Inkludera std-namnomrรฅdet i vรฅr kod fรถr att anvรคnda dess klasser utan att anropa det.
- Skapa en klass som heter ClassA.
- Anvรคnd public access modifier fรถr att markera en klassmedlem som allmรคnt tillgรคnglig.
- Skapa en virtuell funktion som heter show(). Det blir en offentlig funktion.
- Texten som ska skrivas ut nรคr show() anropas anropas. Slutet รคr en C++ nyckelord, vilket betyder slutrad. Den flyttar muspekaren till nรคsta rad.
- Slutet pรฅ kroppen av den virtuella funktionen show().
- Slutet pรฅ kroppen av klassen Klass A.
- Skapar en ny klass med namnet ClassB som รคrver klassen ClassA. KlassA blir basklassen medan KlassB blir den hรคrledda klassen.
- Anvรคnd public access modifier fรถr att markera en klassmedlem som allmรคnt tillgรคnglig.
- Omdefiniera den virtuella funktionen show() som hรคrleds i basklassen.
- Texten som ska skrivas ut pรฅ konsolen nรคr show()-funktionen definierad i den hรคrledda klassen anropas.
- Slutet pรฅ brรถdtexten fรถr funktionen show().
- Slutet pรฅ kroppen av den hรคrledda klassen, klass B.
- Anropa main()-funktionen. Programlogiken bรถr lรคggas till i dess kropp.
- Skapa en pekarvariabel med namnet a. Den pekar pรฅ klassen som heter ClassA.
- Skapa en instans av klassen med namnet ClassB. Fรถrekomsten fรฅr namnet b.
- Tilldela vรคrdena lagras i adressen b i variabeln a.
- Anropa show()-funktionen definierad i den hรคrledda klassen. Sen bindning har genomfรถrts.
- Slutet pรฅ huvuddelen av funktionen main().
Kompileringstidspolymorfism vs. Run-Time Polymorphism
Hรคr รคr de stora skillnaderna mellan de tvรฅ:
| Kompileringstid polymorfism | Run-time polymorfism |
|---|---|
| Det kallas ocksรฅ tidig bindning eller statisk polymorfism | Det kallas ocksรฅ sen/dynamisk bindning eller dynamisk polymorfism |
| Metoden anropas/anropas under kompileringstiden | Metoden anropas/anropas under kรถrning |
| Implementeras via funktionsรถverbelastning och operatรถrsรถverbelastning | Implementeras via metodรถverstyrning och virtuella funktioner |
| Exempel, metodรถverbelastning. Mรฅnga metoder kan ha liknande namn men olika antal eller typer av argument | Exempel, รถverordnad metod. Mรฅnga metoder kan ha ett liknande namn och samma prototyp. |
| Snabbare exekvering eftersom metodupptรคckten gรถrs under kompileringstiden | Lรฅngsammare exekvering eftersom metodupptรคckare gรถrs under kรถrning. |
| Less flexibilitet fรถr problemlรถsning tillhandahรฅlls eftersom allt รคr kรคnt under kompileringstiden. | Mycket flexibilitet tillhandahรฅlls fรถr att lรถsa komplexa problem eftersom metoder upptรคcks under kรถrning. |
Sammanfattning
- Polymorfism betyder att ha mรฅnga former.
- Det uppstรฅr nรคr det finns en hierarki av klasser som รคr relaterade genom arv.
- Med polymorfism kan en funktion bete sig annorlunda baserat pรฅ objektet som anropar/kallar den.
- I kompileringstidspolymorfism etableras funktionen som ska anropas under kompileringstiden.
- I kรถrtidspolymorfism etableras funktionen som ska anropas under kรถrning.
- Kompileringstidspolymorfism bestรคms genom funktionsรถverbelastning och operatรถrsรถverbelastning.
- Vid funktionsรถverbelastning finns det mรฅnga funktioner med liknande namn men olika argument.
- Parametrarna kan skilja sig รฅt i antal eller typ.
- Vid operatรถrsรถverbelastning definieras en ny betydelse fรถr C++ operatรถrer.
- Runtime polymorfism uppnรฅs genom funktionsรถverstyrning.
- Vid funktionsรถverstyrning ger en hรคrledd klass en ny definition till en funktion definierad i basklassen.







