Virtuaalne funktsioon on ülemklassis määratletud funktsioon, mis peab alamklassis olemas olema, et sellel alamklassil oleks täielik klassimääratlus. Virtuaalsed funktsioonid tuginevad objektorienteeritud programmeerimisparadigmale, mida nimetatakse virtuaalseks pärimiseks, mida kõige sagedamini nähakse C++-s, kasutades märksõna “virtuaalne”. Virtuaalse funktsiooni määratlemiseks on vaja kahte klassi, ülemklassi ja alamklassi. Ülemklass on koht, kus funktsioon esmakordselt deklareeritakse ja võib-olla ka defineeritakse. Alamklass on koht, kus funktsioon on määratletud – või tühistatud, olenevalt sellest, kas funktsioon määratleti ülemklassis.
Virtuaalset funktsiooni saab defineerida kahel viisil. Esiteks võib seda määratleda kui tünni, milles on tühi keha ja see ei tee midagi. Teiseks võib seda määratleda puhta virtuaalse funktsioonina, kus see on superklassi päisefailis defineeritud kui NULL.
Mõlemal metoodikal on eelised ja puudused. Funktsiooni defineerimine tühjendina tagab, et kõigil alamklassidel on selle rakendus, isegi kui see ei tee midagi. Kui aga unustatakse funktsiooni alistada ja see alamklassis korralikult juurutada, ei kuvata sellele viitavaid vigu ega hoiatusi. Seevastu puhta virtuaalfunktsiooni defineerimine nõuab, et igal alamklassil oleks funktsiooni definitsioon ja kui see nii ei ole, ilmuvad vead.
Virtuaalsetele funktsioonidele kehtivad aga samad pärimisreeglid kui mittevirtuaalsetele funktsioonidele, seega ei pruugi enam kui kahe tasemega pärimishierarhiad vajada virtuaalsete funktsioonide selgesõnalist määratlust. Näiteks võib vaadelda klassi A, mis deklareerib virtuaalset funktsiooni, mis on realiseeritud alamklassis B. Klassil B on oma alamklass, klass C. Klass C ei nõua klassi A funktsiooni selgesõnalist määratlust, sest see pärib definitsioon klassist B. Vajadusel võib klass C alistada klassi B funktsiooni või alistada klassi B funktsiooni, samas ka seda kutsudes.
Teises äärmuses ei pea virtuaalseid funktsioone alamklassis määratlema, kui need on selles alamklassis deklareeritud virtuaalseks. Näiteks võib vaadelda klassi A, mis deklareerib virtuaalset funktsiooni ja millel on kaks alamklassi, B ja C. Lisaks võiks ette kujutada, et klassis B on alamklassid D ja E ning alamklassis C on alamklassid F ja G.
Kõigil klassidel B kuni G peab olema klassi A virtuaalne funktsioon kuidagi määratletud. Kui klassis B on A funktsiooni teostus, ei pea klassid D ja E seda uuesti tegema. Võib-olla peavad C alamklassid rakendama A funktsiooni, kuid mõlemad teevad midagi erinevat, nii et funktsiooni määratlemine klassis C ei oleks kasulik. Sel juhul võib funktsiooni kuulutada virtuaalseks klassis C ja selle rakendamine pole vajalik.
Virtuaalsete funktsioonide õppimine võib olla hirmuäratav, kuid õigesti kasutades võivad need vähendada koodi dubleerimist ja muuta koodi üldiselt palju lihtsamaks. Virtuaalsete funktsioonide puhul on aga palju lõkse, eriti seoses mitme pärimisega. Mitme pärimise korral võivad mitmetähenduslikult määratletud virtuaalsed funktsioonid üksteisega konflikti sattuda, mistõttu tuleks neid selles kontekstis kasutada ettevaatusega.