C++ 中的虚函数(virtual function)是面向对象编程中的一个重要概念,它允许子类重新定义从父类继承的方法。当子类对象被当作父类对象使用时,可以通过子类的方法实现来调用子类的方法,而不是父类的方法。这就是多态(polymorphism)的一种表现。
深入理解 C++ 虚函数,我们需要掌握以下几个关键点:
-
虚函数的声明和定义:在父类中,使用
virtual
关键字声明一个函数为虚函数。在子类中,可以重写(override)这个函数,即使用相同的函数名和参数列表。class Parent { public: virtual void foo() { std::cout << "Parent's foo()" << std::endl; } }; class Child : public Parent { public: void foo() override { std::cout << "Child's foo()" << std::endl; } };
-
动态绑定(Dynamic Binding):当通过基类指针或引用调用虚函数时,实际调用的是运行时对象的实际类型所定义的函数。这被称为动态绑定或晚期绑定。
int main() { Parent* ptr = new Child(); ptr->foo(); // 输出 "Child's foo()" delete ptr; return 0; }
-
纯虚函数(Pure Virtual Function):一个虚函数在类定义中不给出实现(即没有函数体),而是在声明后面直接加
= 0
,这样的函数称为纯虚函数。包含纯虚函数的类称为抽象类,不能直接实例化。子类必须提供纯虚函数的实现,才能创建对象。class Abstract { public: virtual void bar() = 0; // 纯虚函数 }; class Concrete : public Abstract { public: void bar() override { std::cout << "Concrete's bar()" << std::endl; } };
-
虚析构函数(Virtual Destructor):如果一个类被设计为基类,并可能被删除,那么它应该有一个虚析构函数。这是因为在删除子类对象时,如果析构函数不是虚的,那么只会调用基类的析构函数,而不会调用子类的析构函数,这可能导致资源泄露。
class Parent { public: virtual ~Parent() { // 释放资源 } }; class Child : public Parent { public: ~Child() { // 释放子类特有的资源 } };
- 虚函数表(Virtual Function Table):C++ 通过虚函数表来实现动态绑定。每个包含虚函数的类都有一个虚函数表,其中包含了指向虚函数的指针。每个对象都有一个指向其类虚函数表的指针。当通过基类指针或引用调用虚函数时,会先查找对象的虚函数表,然后找到对应的函数进行调用。
- 总之深入理解虚函数及其相关概念,可以帮助我们更好地利用面向对象编程的优势,实现代码的复用和扩展。