inheritance (tsz. inheritances)
Az öröklődés az objektumorientált programozás (OOP) egyik alapvető fogalma. Segítségével egy osztály (leszármazott vagy alosztály) örökölheti egy másik osztály (ősosztály vagy szülőosztály) tulajdonságait és metódusait. Ez elősegíti a kód újrafelhasználását, az osztályok közötti kapcsolatokat, és az átláthatóbb programstruktúrát.
Az alábbi példában a Gyumolcs osztályból egy új osztály, az Alma származik:
#include <iostream>
using namespace std;
// Szülőosztály (ősosztály)
class Gyumolcs {
public:
void szin() {
cout << "A gyümölcsnek van egy színe." << endl;
}
};
// Leszármazott osztály (gyermekosztály)
class Alma : public Gyumolcs {
public:
void fajta() {
cout << "Ez egy piros alma." << endl;
}
};
int main() {
Alma a;
a.szin(); // Örökölt metódus
a.fajta(); // Saját metódus
return 0;
}
Kimenet:
A gyümölcsnek van egy színe. Ez egy piros alma.
Az Alma osztály megörökölte a Gyumolcs osztály szin() metódusát, így azt anélkül tudjuk használni, hogy újra kellene definiálni.
C++-ban az öröklés három módja lehetséges:
Módosító | Mit örököl az alosztály? |
---|---|
public
|
A public tagok nyilvánosak maradnak, a protected tagok öröklődnek, de private maradnak
|
protected
|
A public és protected tagok protected-ként öröklődnek
|
private
|
Az összes örökölt tag private lesz az alosztályban |
class A {
public:
int x; // Nyilvános tag
protected:
int y; // Védett tag
private:
int z; // Privát tag (NEM öröklődik!)
};
class B : public A {
// x továbbra is public, y marad protected, z nem elérhető
};
class C : protected A {
// x és y protected lesz, z nem elérhető
};
class D : private A {
// x és y private lesz, z nem elérhető
};
A konstruktorokat nem örökli az alosztály, de az ősosztály konstruktorát meg kell hívni az alosztály konstruktorában.
class Szulo {
public:
Szulo() {
cout << "Szülőosztály konstruktora meghívva." << endl;
}
~Szulo() {
cout << "Szülőosztály destruktora meghívva." << endl;
}
};
class Gyermek : public Szulo {
public:
Gyermek() {
cout << "Gyermekosztály konstruktora meghívva." << endl;
}
~Gyermek() {
cout << "Gyermekosztály destruktora meghívva." << endl;
}
};
int main() {
Gyermek g;
return 0;
}
Kimenet:
Szülőosztály konstruktora meghívva. Gyermekosztály konstruktora meghívva. Gyermekosztály destruktora meghívva. Szülőosztály destruktora meghívva.
Figyeljük meg, hogy az ősosztály konstruktora előbb, a destruktora pedig utóbb fut le!
A gyermekosztályban felülírhatjuk az ősosztály metódusait. Ehhez a virtual
kulcsszót használjuk:
class Szulo {
public:
virtual void kiir() {
cout << "Ez a szülőosztály." << endl;
}
};
class Gyermek : public Szulo {
public:
void kiir() override { // Felüldefiniálás
cout << "Ez a gyermekosztály." << endl;
}
};
int main() {
Szulo* p;
Gyermek g;
p = &g;
p->kiir(); // A gyermek osztály függvénye hívódik meg a dinamikus kötés miatt
return 0;
}
Kimenet:
Ez a gyermekosztály.
Ha nincs virtual
kulcsszó, akkor az ősosztály metódusa hívódna meg.
Egy osztály több ősosztályt is örökölhet:
class Motor {
public:
void teljesitmeny() {
cout << "Ez egy erős motor!" << endl;
}
};
class Auto {
public:
void marka() {
cout << "Ez egy sportautó." << endl;
}
};
class Sportauto : public Motor, public Auto {};
int main() {
Sportauto s;
s.teljesitmeny();
s.marka();
return 0;
}
Kimenet:
Ez egy erős motor! Ez egy sportautó.
A gyémántprobléma akkor lép fel, ha egy osztály két szülőosztályból örököl, amelyek egy közös ősből származnak:
class Alap {
public:
void uzenet() {
cout << "Alap osztályból" << endl;
}
};
class Szulo1 : public Alap {};
class Szulo2 : public Alap {};
// Probléma: Kétszer öröklődik az Alap osztály
class Gyermek : public Szulo1, public Szulo2 {};
int main() {
Gyermek g;
// g.uzenet(); // HIBA: Nem egyértelmű, melyik uzenet() függvényt használja!
return 0;
}
Megoldás: virtuális öröklődés:
class Alap {
public:
void uzenet() {
cout << "Alap osztályból" << endl;
}
};
class Szulo1 : virtual public Alap {};
class Szulo2 : virtual public Alap {};
class Gyermek : public Szulo1, public Szulo2 {};
int main() {
Gyermek g;
g.uzenet(); // Most már egyértelmű!
return 0;
}
Kimenet:
Alap osztályból
Az öröklődés a kód újrafelhasználásának egyik legfontosabb eszköze C++-ban. A legfontosabb pontok:
public
, protected
, private
.override
) és virtuális függvények.