Prev Next Up Title Contents Index

Miksi pitää olla virtuaalinen hajottaja?


Nimenomaan olio- osoittimien takia perusluokan mahdolliset muutettavat funktiot on esiteltävä virtuaalisiksi. Samoin olio- osoittimien takia myös kantaluokan hajottaja on esiteltävä virtuaaliseksi. Miksi? Lisätään edelliseen esimerkkiin vielä dynaaminen ympyrä:

	...
	p = new cyYmpyra(11,12,13);
	p->sytyta();
	delete p;
	...
Miksi ~caKuvio pitää olla virtuaalinen ja miksi jälkeläisiin pitää esitellä oma hajottaja? Eikö riittäisi että abstraktin kuvion hajottaja olisi muotoa
	~caKuvio() { sammuta(); }                                            
Tässähän sammuta() kutsuu virtuaalitaulun kautta piirtämisfunktiota ja koska p osoittaa ympyrän tietoihin, niin vieläpä ympyrän piirtämistä? Ei riitä! Nimittäin jos kuvion hajottaja ei ole virtuaalinen, kutsutaan operaattorilla delete p suoraan kuvion hajottajaa ja olion tyyppinä pidettäisiin kuviota. Tällöin käytetäisiin kuvion pure virtual- funktiota, joka on laitonta. Entä kelpaisiko jos graafisen olion hajottaja olisi muotoa:
	virtual ~caKuvio() { sammuta(); }                                    
mutta ympyrällä EI olisi omaa hajottajaa? Tämäkään ei kelpaa! Hajottaja toimii siten, että se "vaihtaa" olion virtuaalitaulun osoittimen (vptr) aina osoittamaan sen luokan virtuaalitaulua (vtbl), jonka luokan hajottajaa ollaan suorittamassa. Eli ensin oltaisiin ympyrän virtuaalitaulussa, jossa ei olisi hajottajaa. Seuraavaksi oltaisiin säteellisen kuvion virtuaalitaulussa, jossa ei myöskään olisi hajottajaa. Lopulta ~caKuvion kutsuma sammuta() suorittaa taas laittoman kutsun caKuvio::piirra(). Siis vptr "pienenee" luokkahierarkian purkautuessa kun perittyjen luokkien hajottajia käydään läpi. Itse asiassa myös muodostaja toimii vastaavasti. Muodostajan kussakin vaiheessa olion vptr osoittaa sen luokan virtuaalitauluun, jonka luokan muodostajassa ollaan menossa. Viimeisenähän ollaan aina itse juuri muodostettavan luokan muodostajassa ja näin vptr jää osoittamaan hajottajaan saakka oikeata arvoa! (Viimeinen versio hajottajasta toimisi tässä erikoistapauksessa jos ympyrällä on oma hajottaja: ympyrän sammutahan laittaa nakyy=0, jolloin ~caKuvion kutsuma sammuta ei teekään mitään.) Eli hajottajan tulee olla virtuaalinen ja sen tulee "perua" ainoastaan ne toimenpiteet, joita saman luokan muodostaja tai jokin muu metodi on suorittanut! Ei saa yrittää "korjata" mahdollisia tulevien luokkien jälkiä hajottajassa!

Tehtävä 1.18 Miksi metodit virtuaalisiksi

Keksi esimerkki, joka havainnollistaa miksi kantaluokan hajottajan tulee olla virtuaalinen. Keksi myös esimerkki miksei ei- virtuaalista metodia ole suotavaa määritellä uudelleen.


Prev Next Up Title Contents Index