The compiler builds a vtable (virtual table) for each class with virtual functions. The vtable stores function pointers for every virtual function in that class. Each object with virtual functions has a hidden pointer to its class's vtable.
When you call a virtual function, the program follows the pointer to the vtable and jumps to the right address. This adds one pointer per object and one indirect jump per call. The performance cost is minimal, but the flexibility is huge.