Voitaisiin esimerkiksi rakentaa graafista kirjastoa ja haluttaisiin graafisille olioille seuraavia ominaisuuksia:
Ideaa voidaan kuitenkin jalostaa tekemällä ensin yleinen graafinen olio (caKuvio), jolla on "kaikkien" graafisten olioiden ominaisuudet. Tästä luokasta voidaan sitten periä muita graafisia luokkia, jolloin lisätään vain uuden luokan omat "hienoudet". Yleisestä graafisesta luokasta ei voi olla yhtään ilmentymää (instance), eli varsinaista tätä luokkaa olevaa oliota. Tällaista luokkaa sanotaan abstraktiksi luokaksi.
Aluksi suunnittelemme luokkahierarkian (c=class, a=abstract):
// circle.cpp, esimerkki perinnasta ja luokista/vl-96 // Todellisen piirtämisen sijasta tulostetaan näyttöön keskipiste & koko // tulosta-metodi on vain tätä tarkoitusta varten! #include <stdio.h> //---------------------------------------------------------------------------- class caKuvio { int nakyy; // Sytytetty vai sammutettu void vaihda_paikka(int nx,int ny) { x = nx; y = ny; } protected: // Jos halutaan periä luokkaa, pitää jälkeläisten int x,y; // käyttöön sallittujen attrib. olla protected public: caKuvio(int ix=0, int iy=0) { vaihda_paikka(ix,iy); nakyy = 0; } virtual ~caKuvio() { } int nakyvissa() const { return nakyy; } virtual void piirra() const = 0; // Pure virtual-metodi => abstr. luokka void sammuta() { if ( nakyvissa() ) { nakyy = 0; piirra(); }} void sytyta() { if ( !nakyvissa() ) { nakyy = 1; piirra(); }} void siirra(int nx, int ny) { if ( !nakyvissa() ) { vaihda_paikka(nx,ny); return; } sammuta(); vaihda_paikka(nx,ny); sytyta(); } virtual void tulosta(const char *s="") const { printf("%-10s: %-10s (%02d,%02d)",nakyy?"Sytytetty":"Sammutettu",s,x,y); } }; // caKuvio //---------------------------------------------------------------------------- class caKuvioJollaSade : public caKuvio { int koko(int nr) { r = nr; return 0; } protected: int r; // Uusi atribuutti, koko public: caKuvioJollaSade(int ix=0,int iy=0,int ir=1) : caKuvio(ix,iy), r(ir) {} void muuta_koko(int nr) { // Uutena ominaisuutena koon muuttaminen if ( !nakyvissa() ) { koko(nr); return; } sammuta(); koko(nr); sytyta(); } virtual void tulosta(const char *s="") const { caKuvio::tulosta(s); printf( " r=%d",r); } }; // caKuvioJollaSade //---------------------------------------------------------------------------- class cPiste : public caKuvio { public: cPiste(int ix=0, int iy=0) : caKuvio(ix,iy) {} virtual ~cPiste() { sammuta(); } virtual void piirra() const { tulosta("Piste"); printf("\n"); } }; // cPiste //---------------------------------------------------------------------------- class cYmpyra : public caKuvioJollaSade { public: cYmpyra(int ix=0, int iy=0, int ir=1) : caKuvioJollaSade(ix,iy,ir) {} virtual ~cYmpyra() { sammuta(); } virtual void piirra() const { tulosta("Ympyra"); printf("\n"); } }; // cYmpyra //---------------------------------------------------------------------------- int main(void) { printf("-------------------------------------------------\n"); cPiste p1,p2(10,20); cYmpyra y1(1,1,2); p1.sytyta(); // Sytytetty : Piste (00,00) p2.sytyta(); // Sytytetty : Piste (10,20) p1.siirra(7,8); // Sammutettu: Piste (00,00) // Sytytetty : Piste (07,08) y1.sytyta(); // Sytytetty : Ympyra (01,01) r=2 y1.muuta_koko(5); // Sammutettu: Ympyra (01,01) r=2 // Sytytetty : Ympyra (01,01) r=5 return 0; // Sammutettu: Ympyra (01,01) r=5 // Sammutettu: Piste (10,20) // Sammutettu: Piste (07,08) }Piste on siis perinyt kaikki ominaisuudet graafiselta oliolta ja lisännyt tiedon siitä, miten piste "todellisuudessa" piirretään. Säteellinen olio on myös perinyt graafisen olion ominaisuudet, lisäten vielä olion kokoa kuvaavan suureen. Tästä taas ympyrä voidaan periä suoraan, kunhan kerrotaan miten tietyn kokoinen ympyrä piirretään. Selitämme jatkossa hieman enemmän perinnän syntaksia tämän esimerkin avulla.