跳转到内容

C++ 虚函数

来自代码酷

C++虚函数是面向对象编程中实现运行时多态的核心机制,允许通过基类指针或引用调用派生类的成员函数。本条目将详细讲解其工作原理、语法规则、应用场景及常见问题。

基本概念[编辑 | 编辑源代码]

虚函数(Virtual Function)是通过在基类中使用virtual关键字声明的成员函数,其行为可以在派生类中被重写(override)。当通过基类指针或引用调用虚函数时,程序会根据对象的实际类型动态决定调用哪个版本的函数,这一过程称为动态绑定(Dynamic Binding)或晚期绑定(Late Binding)。

关键特性[编辑 | 编辑源代码]

  • 动态绑定:运行时决定调用的函数版本。
  • 重写规则:派生类函数必须与基类虚函数具有相同的签名(函数名、参数列表、返回类型)。
  • 虚函数表(vtable):编译器为每个含虚函数的类生成一个隐藏的指针数组,存储虚函数地址。

语法与示例[编辑 | 编辑源代码]

基础语法[编辑 | 编辑源代码]

  
class Base {  
public:  
    virtual void show() {  
        std::cout << "Base class show()" << std::endl;  
    }  
};  

class Derived : public Base {  
public:  
    void show() override {  // override关键字(C++11)显式声明重写  
        std::cout << "Derived class show()" << std::endl;  
    }  
};  

int main() {  
    Base* b = new Derived();  
    b->show();  // 输出 "Derived class show()"  
    delete b;  
    return 0;  
}

输出

  
Derived class show()  

纯虚函数与抽象类[编辑 | 编辑源代码]

虚函数可声明为纯虚函数(Pure Virtual),使类成为抽象类(不能实例化):

  
class AbstractBase {  
public:  
    virtual void pureVirtual() = 0;  // 纯虚函数  
};

虚函数表(vtable)原理[编辑 | 编辑源代码]

编译器为每个含虚函数的类生成一个虚函数表,存储指向实际函数的指针。对象内部包含一个指向vtable的指针(vptr)。

classDiagram class Base { +vptr +virtual show() } class Derived { +vptr +show() } Base <|-- Derived note for Base "vtable: Base::show()" note for Derived "vtable: Derived::show()"

实际应用案例[编辑 | 编辑源代码]

场景:图形渲染系统[编辑 | 编辑源代码]

通过基类Shape的虚函数draw()实现多态渲染:

  
class Shape {  
public:  
    virtual void draw() const = 0;  
};  

class Circle : public Shape {  
public:  
    void draw() const override {  
        std::cout << "Drawing a circle" << std::endl;  
    }  
};  

class Square : public Shape {  
public:  
    void draw() const override {  
        std::cout << "Drawing a square" << std::endl;  
    }  
};  

void renderShapes(const std::vector<Shape*>& shapes) {  
    for (const auto& shape : shapes) {  
        shape->draw();  // 动态绑定调用具体实现  
    }  
}

常见问题与注意事项[编辑 | 编辑源代码]

1. 性能开销:虚函数调用比普通函数多一次间接寻址(通过vtable)。 2. 构造函数/析构函数中调用虚函数:此时虚机制未生效,会调用当前类的版本。 3. 默认参数:虚函数的默认参数在编译期确定,建议避免使用。

进阶话题[编辑 | 编辑源代码]

  • 协变返回类型:派生类虚函数可返回基类虚函数返回类型的派生类。
  • 动态类型识别:结合typeiddynamic_cast实现类型安全操作。

协变返回类型示例[编辑 | 编辑源代码]

  
class Base {  
public:  
    virtual Base* clone() const { return new Base(*this); }  
};  

class Derived : public Base {  
public:  
    Derived* clone() const override {  // 返回类型为Derived*  
        return new Derived(*this);  
    }  
};

总结[编辑 | 编辑源代码]

虚函数是C++多态性的基石,通过动态绑定实现灵活的对象行为。理解其底层机制(如vtable)有助于优化性能并避免常见错误。