multiple inheritance (tsz. multiple inheritances)
Az alábbi példában egy osztály (Sportauto
) két másik osztályból (Motor
és Auto
) örököl:
#include <iostream>
using namespace std;
class Motor {
public:
int teljesitmeny;
void motorHang() {
cout << "Brrrr! A motor beindult!" << endl;
}
};
class Auto {
public:
string marka;
void autoAdatok() {
cout << "Ez egy " << marka << " márkájú autó." << endl;
}
};
// Többszörös öröklődés
class Sportauto : public Motor, public Auto {
public:
int sebesseg;
void sportautoInfo() {
cout << "Teljesítmény: " << teljesitmeny << " LE, Max sebesség: " << sebesseg << " km/h" << endl;
}
};
int main() {
Sportauto ferrari;
ferrari.teljesitmeny = 500;
ferrari.marka = "Ferrari";
ferrari.sebesseg = 350;
ferrari.motorHang();
ferrari.autoAdatok();
ferrari.sportautoInfo();
return 0;
}
Kimenet:
Brrrr! A motor beindult! Ez egy Ferrari márkájú autó. Teljesítmény: 500 LE, Max sebesség: 350 km/h
Ha két szülőosztályban ugyanaz a függvény neve, és az alosztály is örökli ezeket, akkor névtérütközés léphet fel:
class A {
public:
void uzenet() {
cout << "Üzenet az A osztályból" << endl;
}
};
class B {
public:
void uzenet() {
cout << "Üzenet a B osztályból" << endl;
}
};
class C : public A, public B {};
int main() {
C obj;
// obj.uzenet(); // HIBA: Nem tudja eldönteni, melyik `uzenet()` függvényt hívja meg!
return 0;
}
A probléma megoldása: az adott osztály megnevezése az elérési úttal:
int main() {
C obj;
obj.A::uzenet(); // Az A osztály uzenet() metódusát hívja
obj.B::uzenet(); // A B osztály uzenet() metódusát hívja
return 0;
}
Kimenet:
Üzenet az A osztályból Üzenet a B osztályból
A gyémántprobléma akkor jelentkezik, amikor egy osztály két különböző szülőosztályból öröklődik, amelyek egy közös ősből származnak.
class Alap {
public:
void uzenet() {
cout << "Üzenet az Alap osztályból" << endl;
}
};
class Szulo1 : public Alap {};
class Szulo2 : public Alap {};
// Hiba! Az Alap osztály két példánya kerül be az Osztaly-ba.
class Osztaly : public Szulo1, public Szulo2 {};
int main() {
Osztaly obj;
// obj.uzenet(); // HIBA! Nem tudja eldönteni, melyik uzenet() metódust használja.
return 0;
}
A gyémántprobléma elkerülésére virtuális öröklést használhatunk:
class Alap {
public:
void uzenet() {
cout << "Üzenet az Alap osztályból" << endl;
}
};
class Szulo1 : virtual public Alap {};
class Szulo2 : virtual public Alap {};
class Osztaly : public Szulo1, public Szulo2 {};
int main() {
Osztaly obj;
obj.uzenet(); // Most már egyértelmű, hogy az Alap osztály metódusa hívódik meg.
return 0;
}
Kimenet:
Üzenet az Alap osztályból
Ha az osztályok absztrakt osztályokat örökölnek, akkor biztosíthatjuk, hogy az alosztályok implementálják a szükséges metódusokat.
class Munka {
public:
virtual void dolgozik() = 0; // Pure virtual függvény
};
class Ember {
public:
string nev;
Ember(string n) : nev(n) {}
};
class Programozo : public Munka, public Ember {
public:
Programozo(string n) : Ember(n) {}
void dolgozik() override {
cout << nev << " kódot ír!" << endl;
}
};
int main() {
Programozo p("Gábor");
p.dolgozik(); // "Gábor kódot ír!"
return 0;
}
Kimenet:
Gábor kódot ír!
A többszörös öröklődés lehetőséget ad arra, hogy egy osztály több szülőosztály tulajdonságait örökölje, de körültekintően kell alkalmazni.
✔️ Több osztály funkcionalitásának kombinálása
✔️ Kód újrafelhasználása
✔️ Rugalmasság az objektumorientált tervezésben
⚠️ Névtérütközés (azonos nevű metódusok öröklése)
⚠️ Gyémántprobléma (ugyanaz az ősosztály többszörös példánya)
⚠️ Bonyolultabb kód és hibakeresés
Ha el akarjuk kerülni a problémákat, érdemes lehet virtuális öröklést és interfész-alapú tervezést alkalmazni.