Nichts im Leben is gratis, so auch nicht virtual. Sobald eine Klasse mindestens eine virtuelle Methode hat, bringt dies auch Nachteile mit sich. Die Vorteile haben wir ja schon beleuchtet: Polymorphismus. Die Nachteile sind nicht gravierend, aber dennoch vorhanden.
Die vtable ist eine Art 'Lookup' Tabelle in der steht, welche Methoden aufgerufen werden soll. Wenn wir ein derived.foo(); machen, dann wird in der vtable nachgesehen welches foo nun aufgerufen werden soll. Weiters stehen Daten über den Typ des Objektes in der vtable - um RTTI (RunTime Type Identification) zu ermöglichen.
Eine vtable vergrößert das Objekt minimal, nämlich um einen Zeiger. Allerdings ist jeder Aufruf einer virtuellen Funktion ein indirektor Aufruf (anstatt die Adresse der Funktion direkt im Code stehen zu haben, muss die Adresse erst über die vtable ermittelt werden). Dies ist natürlich ein bisschen langsamer als ein direkter Aufruf.
Aus diesem Grund kann es auch kein inline mit virtuellen Methoden geben - da der Compiler ja noch nicht weiss, welche Methode er aufrufen muss. Manchmal steht es schon der Compiletime fest, welche Methode aufgerufen wird - dann kann der Compiler inline, allerdings befindet sich die virtuelle Methode dann zweimal in der Binary: einmal geinlinet und einmal 'normal' um über die vtable angesprochen werden zu können.
Deshalb sollte man virtual nur dort verwenden, wo man es braucht. Allerdings sollte man virtual nicht meiden, nur weil es 'langsam' ist - denn das stimmt nicht. Ein Aufruf einer virtuellen Methode ist nicht langsamer als die passende Funktion über ein switch() zu ermitteln. Also: virtual nicht zu häfig einsetzen, aber auf keinen Fall zu selten.