...
Periyttämisestä käytetään myös nimeä erikoistaminen (specialization) ja vastaavasti yhteisten metodien ja muuttujien siirtämistä omaan luokkaansa kutsutaan yleistämiseksi (generalization). Perimimisjärjestyksessä aikaisempaa luokkaa kutsutaan vanhemmaksi (parent) ja siitä perivää luokkaa lapseksi (child).
Periytyminen C++:ssa esitetään seuraavasti:
...
Seuraavassa on esitetty ensin luokka CElain:
elain.h:
Code Block |
---|
class CElain { private: // saatavissa vain luokan funktioilla char m_Kutsumanimi[100]; float m_Massa; public: // voidaan käyttää luokan ulkopuolelta void AsetaNimi(char Nimi[]); char* KysyNimi(); void AsetaMassa(float Massa); float KysyMassa(); }; |
Seuraavaksi on erikoistettu luokka, joka esittää eläintä kissa, siihen sisällytetään kaikki vain kissalle ominaiset piirteet.
kissa.h:
Code Block |
---|
#include "elain.h" class CKissa : public CElain { private: // saatavissa vain luokan funktioilla public: // voidaan käyttää luokan ulkopuolelta void Kehraa(); }; |
Luokka CKissa perii kaikki CElain-luokan ominaisuudet ja toiminnallisuudet (=jäsenmuuttujat ja -funktiot). Mutta ainoastaan protected ja public-tyyppisiin päästään käsiksi CKissa-luokassa. Kts. näkyvyys.
Kuva 1. Esimerkki 1 UML-kielen luokkakaaviona esitettynä.
Vanhemman funktioiden ylikirjoitus perillisessä
...
Esimerkki 2. Funktion ylikirjoitus perillisessä.
elain.h:
Code Block |
---|
#include <iostream><stdio.h> using namespace std; class CElain { public: // voidaan käyttää luokan ulkopuolelta void TulostaLuokanNimi() { cout << printf("Luokan nimi on CElain." << endl\n"); } }; |
lehma.h:
Code Block |
---|
#include "elain.h" class CLehma : public CElain { public: void TulostaLuokanNimi() { cout << printf("Luokan nimi on CLehma." << endl\n"); } }; |
main.cpp:
Code Block |
---|
#include "elain.h"
#include "lehma.h"
int main()
{
CLehma lehma;
lehma.TulostaLuokanNimi();
CElain elain;
elain.TulostaLuokanNimi();
}
|
Kuva 2. Esimerkin 2 luokkakaavio.
Testatkaa mitä main():ssa tehdyt funktiokutsut tulostavat.
Olion jäsenfunktioiden käyttö perillisestä
Vanhemman luokan jäsenfunktioita voidaan kutsua normaalisti, jos niitä ei ole ylikijoitettu.
Jos ne on ylikijoitettu, oletuksena kutsutaan aina perillisen versiota. Mieti seuraavaa tilannetta:
Code Block |
---|
#include "elain.h"
class CLehma : public CElain
{
public:
void TulostaLuokanNimi()
{
TulostaLuokanNimi();
printf("Luokan nimi on CLehma.\n");
}
};
|
Tämä on loputon rekursio, eli funktio kutsuu itseään loputtomasti, sillä siinä ei ole lopetusehtoa.
Jos taas tarkoituksena oli kutsua vanhemman (CElain) TulostaLuokanNimi()-funktiota täytyy se määritellä eksplisiittisesti:
Code Block |
---|
#include "elain.h"
class CLehma : public CElain
{
public:
void TulostaLuokanNimi()
{
CElain::TulostaLuokanNimi();
printf("Luokan nimi on CLehma.\n");
}
};
|
Tämä koodi toimii halutulla tavalla, eli CLehma-luokasta luodun olion TulostaLuokanNimi()-funktio kutsuu ensin vanhempansa, eli CElain-luokan funktiota TulostaLuokanNimi(), jonka jälkeen se tulostaa ruudulle oman tekstinsä.