Kas yra virtuali funkcija?

Virtuali funkcija yra funkcija, apibrėžta superklasėje, kuri turi būti poklasyje, kad tas poklasis turėtų visą klasės apibrėžimą. Virtualios funkcijos remiasi į objektą orientuota programavimo paradigma, vadinama virtualiuoju paveldėjimu, kuri dažniausiai matoma C++ naudojant raktinį žodį „virtualus“. Norint apibrėžti virtualią funkciją, reikalingos dvi klasės – superklasė ir poklasis. Superklasė yra vieta, kur funkcija pirmiausia deklaruojama ir galbūt apibrėžiama. Poklasis yra vieta, kur funkcija yra apibrėžta arba nepaisoma, priklausomai nuo to, ar funkcija buvo apibrėžta superklasėje.

Virtualią funkciją galima apibrėžti vienu iš dviejų būdų. Pirma, jis gali būti apibrėžtas kaip stuburo dalis, kurioje jis turi tuščią korpusą ir nieko nedaro. Antra, ji gali būti apibrėžta kaip gryna virtuali funkcija, kur ji superklasės antraštės faile apibrėžiama kaip NULL.

Abi metodikos turi privalumų ir trūkumų. Funkcijos apibrėžimas kaip šaknis užtikrina, kad visuose poklasiuose ji bus įgyvendinta, net jei ji nieko nedaro. Tačiau jei pamirštama nepaisyti funkcijos ir tinkamai ją įdiegti poklasyje, neatsiras klaidų ar įspėjimų, kurie tai nurodytų. Kita vertus, norint apibrėžti gryną virtualią funkciją, kiekvienas poklasis turi turėti savo funkcijos apibrėžimą, o jei taip nėra, atsiras klaidų.

Tačiau virtualiosioms funkcijoms taikomos tos pačios paveldėjimo taisyklės kaip ir nevirtualioms funkcijoms, todėl paveldėjimo hierarchijoms, turinčioms daugiau nei du lygius, gali nereikėti aiškių virtualių funkcijų apibrėžimų. Pavyzdžiui, galima nagrinėti A klasę, kuri deklaruoja virtualią funkciją, kuri yra įgyvendinta B poklasyje. B klasė turi savo poklasį, klasę C. C klasei nereikia aiškaus A klasės funkcijos apibrėžimo, nes ji paveldi B klasės apibrėžimas. Jei reikia, C klasė gali nepaisyti B klasės funkcijos arba gali nepaisyti B klasės funkcijos, kartu ją iškviesdama.

Kita vertus, virtualios funkcijos neturi būti apibrėžtos poklasyje, jei jos paskelbtos virtualiomis tame poklasyje. Pavyzdžiui, galima nagrinėti A klasę, kuri deklaruoja virtualią funkciją ir turi du poklasius B ir C. Be to, galima įsivaizduoti, kad B klasė turi poklasius D ir E, o C poklasis turi F ir G poklasius.

Visose klasėse nuo B iki G turi būti kažkaip apibrėžta A klasės virtuali funkcija. Jei B klasėje įdiegta A funkcija, D ir E klasėms jos nereikia perdaryti. Galbūt C poklasiams reikia įgyvendinti A funkciją, tačiau jie abu daro kažką skirtingai, todėl apibrėžti funkciją pačioje C klasėje nebūtų naudinga. Tokiu atveju funkcija gali būti paskelbta virtualia C klasėje ir jos įgyvendinti nereikia.
Virtualias funkcijas gali būti nedrąsu išmokti, tačiau tinkamai naudojant jos gali sumažinti kodo dubliavimą ir padaryti kodą daug lengviau suprantamą apskritai. Tačiau virtualiosiose funkcijose yra daug spąstų, ypač susijusių su daugialypiu paveldėjimu. Daugybinio paveldėjimo atveju dviprasmiškai apibrėžtos virtualios funkcijos gali prieštarauti viena kitai, todėl jas reikia naudoti atsargiai.