Vad är en virtuell funktion?
En virtuell funktion är en funktion, definierad i en superklass, som måste finnas i en underklass för att underklassen ska ha en fullständig klassdefinition. Virtuella funktioner förlitar sig på ett objektorienterat programmeringsparadigm som kallas virtuell arv, vilket oftast ses i C ++ med hjälp av det "virtuella" sökordet. För att definiera en virtuell funktion krävs två klasser, en superklass och en underklass. Superklass är där funktionen först deklareras och eventuellt definieras. Underklassen är där funktionen är definierad - eller åsidosatt, beroende på om funktionen definierades i superklassen.
Den virtuella funktionen kan definieras på ett av två sätt. Först kan den definieras som en stubb, där den har en tom kropp och inte gör något. För det andra kan den definieras som en ren virtuell funktion, där den definieras som NULL i superklassens rubrikfil.
Det finns fördelar och nackdelar med båda metoderna. Att definiera en funktion som en stub säkerställer att alla underklasser har någon implementering av den, även om den inte gör någonting. Om man glömmer att åsidosätta funktionen och implementera den ordentligt i en underklass, verkar dock inga fel eller varningar som påpekar detta. Att definiera en ren virtuell funktion kräver å andra sidan varje underklass att ha sin egen definition av funktionen, och fel kommer att visas om detta inte är fallet.
Virtuella funktioner är dock underkastade samma arvsregler som icke-virtuella funktioner, så arvhierarkier med mer än två nivåer kanske inte kräver explicita definitioner av virtuella funktioner. Till exempel kan man överväga en klass A som förklarar en virtuell funktion, som är implementerad i underklass B. Klass B har en egen underklass, klass C. Klass C kräver inte en uttrycklig definition av klass A: s funktion, eftersom den ärver definitionen från klass B. Vid behov kan klass C åsidosätta klass B: s funktion, eller den kan åsidosätta klass B: s funktion samtidigt som den kallas.
I det andra extrema behöver virtuella funktioner inte definieras i en underklass om de förklaras virtuella i den underklassen. Till exempel kan man överväga en klass A som förklarar en virtuell funktion och har två underklasser, B och C. Dessutom kan man föreställa sig att klass B har underklasser D och E, och underklass C har underklasser F och G.
Klass B till G måste alla ha klass A: s virtuella funktion definierad på något sätt. Om klass B har en implementering av A: s funktion, behöver klasserna D och E inte att den ska göras om. Kanske behöver C: s underklasser implementera A: s funktion, men båda gör något annorlunda, så att det inte skulle vara användbart att definiera funktionen i klass C själv. I så fall kan funktionen förklaras virtuell i klass C, och en implementering är inte nödvändig.
Virtuella funktioner kan vara skrämmande att lära sig, men när de används på rätt sätt kan de minska kodduplicering och göra koden mycket lättare att förstå i allmänhet. Det finns dock många fallgropar med virtuella funktioner, särskilt när det gäller flera arv. I flera arv är det möjligt för tvetydigt definierade virtuella funktioner att konflikt med varandra, så de bör användas med försiktighet i det sammanhanget.