Virtualna funkcija je funkcija definirana u nadklasi, koja mora biti prisutna u podklasi da bi ta potklasa imala potpunu definiciju klase. Virtualne funkcije oslanjaju se na objektno orijentiranu programsku paradigmu zvanu virtualno nasljeđivanje, što se najčešće može vidjeti u C++ koristeći ključnu riječ “virtual”. Za definiranje virtualne funkcije potrebne su dvije klase, nadklasa i podklasa. Nadklasa je mjesto gdje je funkcija prvi put deklarirana, a moguće i definirana. Potklasa je mjesto gdje je funkcija definirana – ili nadjačana, ovisno o tome je li funkcija definirana u nadklasi.
Virtualna funkcija može se definirati na jedan od dva načina. Prvo, može se definirati kao stub, u kojem ima prazno tijelo i ne radi ništa. Drugo, može se definirati kao čista virtualna funkcija, gdje je definirana kao NULL u datoteci zaglavlja superklase.
Obje metodologije imaju prednosti i nedostatke. Definiranje funkcije kao stuba osigurava da sve podklase imaju neku njenu implementaciju, čak i ako ne radi ništa. Međutim, ako netko zaboravi nadjačati funkciju i pravilno je implementirati u podklasu, neće se pojaviti pogreške ili upozorenja koja bi to ukazivala. Definiranje čiste virtualne funkcije, s druge strane, zahtijeva da svaka podklasa ima vlastitu definiciju funkcije, a pogreške će se pojaviti ako to nije slučaj.
Virtualne funkcije, međutim, podliježu istim pravilima nasljeđivanja kao i nevirtualne funkcije, tako da hijerarhije nasljeđivanja s više od dvije razine možda neće zahtijevati eksplicitne definicije virtualnih funkcija. Na primjer, može se uzeti u obzir klasa A koja deklarira virtualnu funkciju, koja je implementirana u podklasu B. Klasa B ima svoju podklasu, klasu C. Klasa C ne zahtijeva eksplicitnu definiciju funkcije klase A, jer nasljeđuje definiciju iz klase B. Ako je potrebno, klasa C bi mogla nadjačati funkciju klase B ili bi mogla nadjačati funkciju klase B dok je također poziva.
S druge strane, virtualne funkcije ne moraju biti definirane u podklasi ako su deklarirane kao virtualne u toj podklasi. Na primjer, može se uzeti u obzir klasa A koja deklarira virtualnu funkciju i ima dvije podklase, B i C. Osim toga, moglo bi se zamisliti da klasa B ima podklase D i E, a podklasa C ima podklase F i G.
Sve klase B do G moraju imati na neki način definiranu virtualnu funkciju klase A. Ako klasa B ima implementaciju funkcije A, klase D i E ne trebaju je ponovno raditi. Možda C-ove podklase trebaju implementirati A-ovu funkciju, ali obje rade nešto drugačije, tako da definiranje funkcije u samoj klasi C ne bi bilo korisno. U tom slučaju, funkcija se može deklarirati virtualnom u klasi C, a implementacija nije potrebna.
Virtualne funkcije mogu biti zastrašujuće za učenje, ali kada se koriste pravilno, mogu smanjiti dupliciranje koda i općenito učiniti kod mnogo lakšim za razumijevanje. Međutim, postoje mnoge zamke s virtualnim funkcijama, posebno u vezi s višestrukim nasljeđivanjem. Kod višestrukog nasljeđivanja moguće je da dvosmisleno definirane virtualne funkcije budu u sukobu jedna s drugom, pa ih u tom kontekstu treba koristiti s oprezom.