Wat is een virtuele functie?
Een virtuele functie is een functie, gedefinieerd in een superklasse, die aanwezig moet zijn in een subklasse voordat die subklasse een volledige klassedefinitie heeft. Virtuele functies vertrouwen op een objectgeoriënteerd programmeerparadigma genaamd virtuele overerving, dat meestal wordt gezien in C ++ met behulp van het trefwoord "virtueel". Om een virtuele functie te definiëren, zijn twee klassen nodig, een superklasse en een subklasse. In de superklasse wordt de functie eerst gedeclareerd en mogelijk gedefinieerd. In de subklasse wordt de functie gedefinieerd of overschreven, afhankelijk van of de functie in de superklasse is gedefinieerd.
De virtuele functie kan op twee manieren worden gedefinieerd. Ten eerste kan het worden gedefinieerd als een stomp, waarin het een leeg lichaam heeft en niets doet. Ten tweede kan het worden gedefinieerd als een pure virtuele functie, waar het wordt gedefinieerd als NULL in het header-bestand van de superklasse.
Beide methoden hebben voor- en nadelen. Het definiëren van een functie als een stub zorgt ervoor dat alle subklassen enige implementatie ervan hebben, zelfs als het niets doet. Als men vergeet de functie te negeren en deze correct in een subklasse te implementeren, zullen er echter geen fouten of waarschuwingen op wijzen. Voor het definiëren van een pure virtuele functie is echter vereist dat elke subklasse een eigen definitie van de functie heeft en fouten verschijnen als dit niet het geval is.
Virtuele functies zijn echter onderworpen aan dezelfde overervingsregels als niet-virtuele functies, dus overervinghiërarchieën met meer dan twee niveaus vereisen mogelijk geen expliciete definities van virtuele functies. Men kan bijvoorbeeld een klasse A beschouwen die een virtuele functie declareert, die is geïmplementeerd in subklasse B. Klasse B heeft een eigen subklasse, klasse C. Klasse C vereist geen expliciete definitie van de functie van klasse A, omdat deze erfelijk is de definitie uit klasse B. Indien nodig kan klasse C de functie van klasse B vervangen, of het kan de functie van klasse B vervangen terwijl het ook wordt aangeroepen.
Aan het andere uiterste hoeven virtuele functies niet in een subklasse te worden gedefinieerd als ze in die subklasse virtueel worden verklaard. Men kan bijvoorbeeld een klasse A beschouwen die een virtuele functie aangeeft en twee subklassen heeft, B en C. Bovendien zou men zich kunnen voorstellen dat klasse B subklassen D en E heeft, en subklasse C heeft subklassen F en G.
Voor klassen B tot en met G moet de virtuele functie van klasse A op de een of andere manier zijn gedefinieerd. Als klasse B een implementatie van de functie van A heeft, hoeven klassen D en E deze niet opnieuw te doen. Misschien moeten de subklassen van C de functie van A implementeren, maar ze doen allebei iets anders, dus het definiëren van de functie in klasse C zelf zou niet nuttig zijn. In dat geval kan de functie in klasse C virtueel worden verklaard en is een implementatie niet nodig.
Virtuele functies kunnen ontmoedigend zijn om te leren, maar bij correct gebruik kunnen ze codeduplicaties verminderen en code in het algemeen veel gemakkelijker te begrijpen maken. Er zijn echter veel valkuilen met virtuele functies, vooral met betrekking tot meervoudige overerving. Bij meervoudige overerving is het mogelijk dat dubbelzinnige gedefinieerde virtuele functies met elkaar conflicteren, dus moeten ze in die context met voorzichtigheid worden gebruikt.