Metodin/funktion virtuaalisuudella määrätään se, mitä metodia kutsutaan. Ei- virtuaalisia metodia kutsutaan aina siitä luokasta (perintätasosta), jossa niiden kutsu on määritelty (early binding, kutsu selviää käännösaikana).
Ympyrä- esimerkissä graafisen olion siirto poistaa olion näytöltä "piirtämällä" olion uudelleen (oikeasti XOR-kynällä tai negatiivisella värillä). Sitten olio piirretään uuteen paikkaansa. Itse toiminnot ovat tietysti samoja pisteelle ja ympyrälle, mutta pisteen piirtämisen sijasta pitääkin piirtää ympyrä. Määrittelemällä graafisen olion piirtometodi virtuaaliseksi, saadaan perinnässä siirra-metodi kutsumaan ylimmän mahdollisen luokan piirra-metodia (myöhäinen sidonta, late binding, kutsu selviää ajon aikana).
Joskus - kuten tässä esimerkissä - ylimpään luokkaan halutaan virtuaalinen metodi, mutta sille ei ole mitään järkevää toimintaa. Kuitenkin halutaan, että johdetuissa luokissa metodi on pakko esitellä. Tällöin käytetään pelkkää virtuaalista metodia (pure virtual):
virtual void piirra() = 0;Luokkaa, jossa on yksikin pelkkä virtuaalinen metodi, sanotaan abstraktiksi luokaksi (abstract class), koska tällaista luokkaa voidaan käyttää vain perimiseen (eli luokasta ei voi olla ilmentymää, instance).
Huomautus! Jos luokkaa on tarkoitus käyttää perusluokkana (sitä voidaan periä), on syytä esitellä kaikki mahdollisesti joskus muutettavat metodit virtuaalisiksi. Erityisesti hajottaja PITÄÄ aina esitellä virtuaaliseksi perusluokassa (yliluokassa, superclass)!
Toisaalta jos luokkaa ei ole tarkoitus käyttää perusluokkana, ei siihen ole syytä esitellä yhtään virtuaalista metodia (ei edes hajottajaa virtuaalisena). Syynä tähän on virtuaalimetodien toteutus virtuaalitaulun (vtbl = virtual table) ja sen osoittimen (vptr=virtual table pointer) avulla:
Kuvasta on jätetty tulosta - metodi esittämättä
|
sytyta-metodi kääntyy suurinpiirtein seuraavasti: void caKuvio::sytyta() { if ( !this->nakyy ) { this->nakyy = 1; this->vptr->piirra(); } } |
Toisaalta usein sanotaan virtuaalisten metodien kutsujen olevan hitaampia kuin vastaavien ei- virtuaalisten metodien kutsujen. Tämä on totta esimerkiksi sytyta-funktiossa. Jos kuitenkin kutsutaan p1.piirra(), niin kääntäjä voi heti ratkaista oikean kutsun käännösaikana käyttämättä virtuaalitaulua apuna. Olio- osoittimen tapauksessa kutsu p->piirra() joudutaan ratkaisemaan ajon aikana virtuaalitaulun avulla.