虚函数是C++实现运行时多态的核心机制,通过virtual声明、vtable动态绑定实现基类指针调用派生类重写函数;析构函数应为虚函数,构造函数不能为虚函数,纯虚函数定义抽象类。
虚函数是 C++ 中实现运行时多态的核心机制,它允许基类指针或引用调用派生类中重写的函数,具体执行哪个版本由对象的实际类型决定,而不是指针或引用的静态类型。
在基类中用 virtual 关键字修饰成员函数,就把它变成虚函数。派生类中同名、同参数、同返回类型的函数会自动成为虚函数(即使不写 virtual),也可以显式加上 override(推荐)来增强可读性和编译检查。
对象还没完全生成)C++ 编译器为含有虚函数的类生成一个虚函数表(vtable),每个对象开头隐含一个指向该表的指针(vptr)。vtable 中按声明顺序存放虚函数地址。当通过基类指针调用虚函数时,程序查 vptr → 找 vtable → 取对应函数地址 → 跳转执行,这个过程在运行时完成,所以叫“动态绑定”或“晚绑定”。
虚函数不是万能的,用错反而引发问题。比如,把不该多态的函数设为虚函数会增加对象体积(每个对象多一个 vptr)和调用开销(间接跳转);反过来,该虚却不虚,就无法体现多态行为。
下面代码展示了虚函数如何支撑多态:
#includeusing namespace std; class Animal { public: virtual void speak() { cout << "Animal makes a sound\n"; } virtual ~Animal() = default; // 虚析构很重要 };
class Dog : public Animal { public: void speak() override { cout << "Dog barks\n"; } };
class Cat : public Animal { public: void speak() override { cout << "Cat meows\n"; } };
int main() { Animal a1 = new Dog(); Animal a2 = new Cat(); a1->speak(); // 输出 Dog barks a2->speak(); // 输出 Cat meows delete a1; delete a2; }
输出结果取决于 new 出来的实际对象类型,而不是 Animal* 的类型 —— 这就是多态的本质。