dynamic dispatch
| polymorphism |
|---|
| ad hoc polymorphism |
| parametric polymorphism |
| subtyping |
Főnév
dynamic dispatch (tsz. dynamic dispatches)
- (informatika) A dinamikus diszpécselés (dynamic dispatch) azt jelenti, hogy a program futási időben dönti el, melyik metódust hívja meg egy polimorf osztályhierarchiában. Ez az öröklődés és a virtuális függvények segítségével valósítható meg C++-ban.
Statikus vs. dinamikus diszpécselés
- Statikus diszpécselés (compile-time dispatch)
- A metódushívás már fordítási időben eldől.
- Például ha nincs virtuális függvény, a fordító a deklarált típus alapján dönti el, melyik metódust kell hívni.
- Dinamikus diszpécselés (runtime dispatch)
- A metódushívás futási időben történik a virtuális függvénytáblán (VTable) keresztül.
- Ez biztosítja, hogy a megfelelő, származtatott osztálybeli függvény fusson le, ha egy
Base*vagyBase&típusú változót használunk.
Dinamikus diszpécselés példája (virtuális függvényekkel)
Alapvető példa
#include <iostream>
class Base {
public:
virtual void print() { // Virtuális függvény
std::cout << "Base osztály print()" << std::endl;
}
};
class Derived : public Base {
public:
void print() override { // Felülírja a virtuális függvényt
std::cout << "Derived osztály print()" << std::endl;
}
};
int main() {
Base* obj = new Derived(); // Dinamikus allokáció
obj->print(); // Futási időben dől el, hogy a Derived::print() hívódik meg
delete obj;
return 0;
}
Kimenet:
Derived osztály print()
Mi történik itt? - Az obj egy Base* típusú pointer, de valójában egy Derived objektumot mutat. - Az obj->print() híváskor a program nem a Base verzióját hívja, hanem a Derived::print() metódust. - Ez azért lehetséges, mert a print() függvény virtuális, és így dinamikus diszpécselést használ.
Hogyan működik a dinamikus diszpécselés?
A dinamikus diszpécselés a virtuális táblát (VTable) és a virtuális pointert (VPTR) használja.
- Minden osztály, amely tartalmaz virtuális függvényeket, kap egy VTable-t.
- A VTable egy olyan struktúra, amely a virtuális függvények mutatóit tárolja.
- Minden példány tartalmaz egy VPTR mutatót, amely a megfelelő VTable-ra mutat.
- Amikor egy virtuális függvényt hívunk, a program a VPTR segítségével a megfelelő VTable-ből választja ki a megfelelő függvényt.
Pure Virtual Functions és Absztrakt Osztályok
Ha egy osztályban van pure virtual function, az osztály absztrakt osztály lesz, és nem példányosítható.
Példa egy absztrakt osztályra:
#include <iostream>
class Shape {
public:
virtual void draw() = 0; // Pure virtual function (kötelező felülírni)
};
class Circle : public Shape {
public:
void draw() override {
std::cout << "Kör kirajzolása" << std::endl;
}
};
int main() {
// Shape obj; // Ez NEM működik, mert Shape absztrakt osztály!
Shape* s = new Circle();
s->draw(); // Futási időben a Circle::draw() hívódik meg
delete s;
return 0;
}
Kimenet:
Kör kirajzolása
Mi történik itt? - A Shape osztályban a draw() pure virtual function (= 0). - A Shape absztrakt osztály, tehát nem példányosítható. - A Circle osztály felülírja a draw() függvényt. - A s->draw(); hívás a Circle::draw() függvényt hívja meg dinamikusan.
Virtuális destruktorok – Fontos!
Ha egy osztályt dinamikusan öröklődő polimorf objektumokként használunk, a destruktorának virtuálisnak kell lennie, különben memóriaszivárgás léphet fel.
Helytelen destruktor (memóriaszivárgást okozhat):
#include <iostream>
class Base {
public:
~Base() { std::cout << "Base destruktor" << std::endl; }
};
class Derived : public Base {
public:
~Derived() { std::cout << "Derived destruktor" << std::endl; }
};
int main() {
Base* obj = new Derived();
delete obj; // Csak a Base destruktora hívódik meg! (Derived destruktora NEM!)
return 0;
}
Kimenet:
Base destruktor
A Derived destruktora NEM fut le, ami memóriaszivárgást okozhat.
Helyes megoldás (virtuális destruktorral):
#include <iostream>
class Base {
public:
virtual ~Base() { std::cout << "Base destruktor" << std::endl; }
};
class Derived : public Base {
public:
~Derived() { std::cout << "Derived destruktor" << std::endl; }
};
int main() {
Base* obj = new Derived();
delete obj; // Most mindkét destruktor meghívódik
return 0;
}
Kimenet:
Derived destruktor Base destruktor
Megjegyzés: Ha egy osztály rendelkezik virtuális függvényekkel, akkor a destruktorát is mindig virtuálisnak kell megadni!
Összegzés
- Dinamikus diszpécselés azt jelenti, hogy a megfelelő függvény futási időben kerül kiválasztásra.
- Virtuális függvények (
virtual) biztosítják a dinamikus kötést. - VTable és VPTR mechanizmus segítségével működik.
- Pure virtual function (
= 0) absztrakt osztályokat hoz létre. - Virtuális destruktor (
virtual ~Destructor()) megakadályozza a memóriaszivárgást.
Ha polimorfikus osztályokat használsz, mindig gondoskodj a helyes destruktorok beállításáról, hogy elkerüld a memória problémákat! 🚀
- dynamic dispatch - Szótár.net (en-hu)
- dynamic dispatch - Sztaki (en-hu)
- dynamic dispatch - Merriam–Webster
- dynamic dispatch - Cambridge
- dynamic dispatch - WordNet
- dynamic dispatch - Яндекс (en-ru)
- dynamic dispatch - Google (en-hu)
- dynamic dispatch - Wikidata
- dynamic dispatch - Wikipédia (angol)