polymorphism |
---|
ad hoc polymorphism |
parametric polymorphism |
subtyping |
polymorphism (tsz. polymorphisms)
A polimorfizmus (polymorphism) az objektumorientált programozás (OOP) egyik legfontosabb jellemzője C++-ban. Ez lehetővé teszi, hogy ugyanazt a függvényhívást különböző objektumok eltérően kezeljék. A polimorfizmus segítségével rugalmasabb és könnyebben bővíthető kódokat írhatunk.
A polimorfizmus szó jelentése: “sok alakúság”. Ez azt jelenti, hogy egy azonos interfésszel rendelkező függvény vagy objektum különbözőképpen viselkedhet a helyzettől függően.
A polimorfizmusnak két fő típusa van C++-ban:
Polimorfizmus típusa | Leírás |
---|---|
Fordítási idejű polimorfizmus (Compile-time polymorphism) | A program fordításakor dől el (pl. függvény túlterhelés, operátor túlterhelés, template-ek). |
Futásidejű polimorfizmus (Runtime polymorphism) | A program futásakor dől el (pl. virtuális függvények, öröklés). |
A fordítási idejű polimorfizmus azt jelenti, hogy a fordító már a kód fordítása során eldönti, melyik függvény vagy operátor hívódjon meg.
Ugyanazon nevű függvény többféle verzióját hozhatjuk létre különböző paraméterekkel.
#include <iostream>
using namespace std;
class Szamol {
public:
void osszead(int a, int b) {
cout << "Osszeg (int): " << a + b << endl;
}
void osszead(double a, double b) {
cout << "Osszeg (double): " << a + b << endl;
}
};
int main() {
Szamol sz;
sz.osszead(5, 10); // Meghívja az int verziót
sz.osszead(3.5, 2.2); // Meghívja a double verziót
}
Osszeg (int): 15 Osszeg (double): 5.7
💡 Fordítási időben eldől, hogy melyik függvény hívódik meg.
A +
, -
, *
, /
és más operátorokat felülírhatjuk egy osztályon belül.
#include <iostream>
using namespace std;
class Szam {
public:
int ertek;
Szam(int e) {
ertek = e;
}
Szam operator+(const Szam& masik) {
return Szam(ertek + masik.ertek);
}
void kiir() {
cout << "Ertek: " << ertek << endl;
}
};
int main() {
Szam sz1(10), sz2(20);
Szam eredmeny = sz1 + sz2; // Az operator+ meghívódik
eredmeny.kiir(); // Kiírja: Ertek: 30
}
A futásidejű polimorfizmus azt jelenti, hogy a program futásakor dől el, melyik függvényhívás történik meg. Ehhez általában öröklést és virtuális függvényeket használunk.
A C++ késleltetett kötést használ, ha egy függvény virtuális (virtual
).
#include <iostream>
using namespace std;
class Allat {
public:
virtual void hang() { // Virtuális függvény
cout << "Az allat hangot ad ki." << endl;
}
};
class Kutya : public Allat {
public:
void hang() override { // Felülírás
cout << "Vau Vau!" << endl;
}
};
int main() {
Allat* allatom = new Kutya();
allatom->hang(); // Kiírja: Vau Vau! (nem az alap osztályt hívja meg!)
delete allatom;
}
Vau Vau!
💡 A virtual
kulcsszó miatt a C++ a Kutya osztály hang()
függvényét hívja meg.
Ha nincs virtual
, akkor az Allat
osztály verziója hívódna meg.
Ha egy osztály csak interfészként szolgál és nem akarjuk példányosítani, használhatunk absztrakt osztályt.
#include <iostream>
using namespace std;
class Allat {
public:
virtual void hang() = 0; // Tisztán virtuális függvény
};
class Kutya : public Allat {
public:
void hang() override {
cout << "Vau Vau!" << endl;
}
};
class Macska : public Allat {
public:
void hang() override {
cout << "Miau!" << endl;
}
};
int main() {
Allat* kutyam = new Kutya();
kutyam->hang(); // Kiírja: Vau Vau!
Allat* macskam = new Macska();
macskam->hang(); // Kiírja: Miau!
delete kutyam;
delete macskam;
}
Mi történik itt? - Az Allat
osztály egy absztrakt osztály, mert van benne tisztán virtuális függvény (= 0
). - Nem lehet példányosítani (Allat allatom;
nem működne). - A leszármazott osztályok implementálják a hang()
függvényt, így minden állat másképp viselkedik.
✔ Amikor különböző osztályok hasonló viselkedést kell, hogy mutassanak.
✔ Ha dinamikusan akarunk objektumokat kezelni és kiterjeszthető rendszert akarunk létrehozni.
✔ Amikor az alaposztály interfészként szolgál és az alosztályok határozzák meg a konkrét működést.
Polimorfizmus típusa | Példa | Mikor használjuk? |
---|---|---|
Függvény túlterhelés (Function Overloading) | Ugyanaz a függvény más paraméterekkel | Ha ugyanazt a műveletet többféleképpen akarjuk végrehajtani |
Operátor túlterhelés (Operator Overloading) | + , - , * stb. operátorok módosítása
|
Ha osztályokat akarunk intuitívan összehasonlítani/műveleteket végezni rajtuk |
Virtuális függvények (Virtual Functions) | Alaposztályból öröklött függvények felülírása | Ha az alosztályoknak különböző viselkedést kell mutatniuk |
Tisztán virtuális függvények (Abstract Classes) | Alaposztály interfészként | Ha biztosak vagyunk benne, hogy az alaposztályból nem lesz példány |