Explain virtual functions and runtime polymorphism. How does a compiler implement virtual functions behind the scenes?