1. 虚函数基础概念

1.1 什么是虚函数

虚函数是用 virtual 关键字声明的成员函数,它支持动态绑定,使得程序能在运行时根据对象的实际类型调用相应的函数。

class Base {
public:
    virtual void show() {  // 虚函数
        cout << "Base::show()" << endl;
    }
    
    void display() {       // 非虚函数
        cout << "Base::display()" << endl;
    }
};
 
class Derived : public Base {
public:
    void show() override {  // 重写虚函数
        cout << "Derived::show()" << endl;
    }
    
    void display() {       // 隐藏基类函数
        cout << "Derived::display()" << endl;
    }
};

1.2 静态绑定 vs 动态绑定

int main() {
    Derived d;
    Base* ptr = &d;
    Base& ref = d;
    
    // 动态绑定(运行时决定)
    ptr->show();     // 输出: Derived::show()
    ref.show();      // 输出: Derived::show()
    
    // 静态绑定(编译时决定)
    ptr->display();  // 输出: Base::display()
    ref.display();   // 输出: Base::display()
}

2. 虚函数表(Virtual Table)机制

2.1 虚表的结构

class Base {
public:
    virtual void func1() { cout << "Base::func1" << endl; }
    virtual void func2() { cout << "Base::func2" << endl; }
    virtual void func3() { cout << "Base::func3" << endl; }
    void func4() { cout << "Base::func4" << endl; }  // 非虚函数
private:
    int base_data;
};
 
class Derived : public Base {
public:
    void func1() override { cout << "Derived::func1" << endl; }
    virtual void func5() { cout << "Derived::func5" << endl; }
private:
    int derived_data;
};

内存布局示意:

Base对象内存布局:
+----------+
| vptr     | -----> Base虚表
+----------+        +----------------+
| base_data|        | &Base::func1   |
+----------+        | &Base::func2   |
                    | &Base::func3   |
                    +----------------+
 
Derived对象内存布局:
+-------------+
| vptr        | -----> Derived虚表
+-------------+        +------------------+
| base_data   |        | &Derived::func1  | (重写)
+-------------+        | &Base::func2     | (继承)
| derived_data|        | &Base::func3     | (继承)
+-------------+        | &Derived::func5  | (新增)
                       +------------------+

2.2 查看虚表内容(实验性代码)

#include <iostream>
#include <cstring>
using namespace std;
 
class Base {
public:
    virtual void f() { cout << "Base::f" << endl; }
    virtual void g() { cout << "Base::g" << endl; }
    virtual void h() { cout << "Base::h" << endl; }
};
 
class Derived : public Base {
public:
    void f() override { cout << "Derived::f" << endl; }
    virtual void i() { cout << "Derived::i" << endl; }
};
 
// 函数指针类型
typedef void(*Fun)(void);
 
void printVTable(Base* obj, const string& className) {
    cout << "=== " << className << " 虚表 ===" << endl;
    
    // 获取vptr(虚表指针)
    void** vptr = *(void***)obj;
    
    // 遍历虚表
    for (int i = 0; vptr[i] != nullptr && i < 10; i++) {
        cout << "虚函数[" << i << "] 地址: " << vptr[i];
        
        // 尝试调用(危险操作,仅用于演示)
        Fun func = (Fun)vptr[i];
        cout << " -> ";
        func();
    }
    cout << endl;
}
 
int main() {
    Base b;
    Derived d;
    
    printVTable(&b, "Base");
    printVTable(&d, "Derived");
    
    return 0;
}

3. 虚函数的内部实现

3.1 虚函数调用过程

class Animal {
public:
    virtual void makeSound() {
        cout << "Animal sound" << endl;
    }
};
 
class Dog : public Animal {
public:
    void makeSound() override {
        cout << "Woof!" << endl;
    }
};
 
int main() {
    Dog dog;
    Animal* ptr = &dog;
    
    // ptr->makeSound() 的实际执行过程:
    // 1. 获取对象的vptr
    // 2. 通过vptr找到虚表
    // 3. 在虚表中找到makeSound的地址(通常是第一个槽位)
    // 4. 调用该地址的函数
    
    ptr->makeSound();  // 相当于: (*(ptr->vptr[0]))(ptr)
}

3.2 汇编层面的实现(简化版)

; ptr->makeSound() 的汇编代码(简化)
mov rax, [ptr]           ; 获取对象地址
mov rcx, [rax]           ; 获取vptr(对象的第一个成员)
mov rdx, [rcx]           ; 获取虚表中第一个函数地址
call rdx                 ; 调用虚函数

4. 特殊情况和边界案例

4.1 构造函数中的虚函数

class Base {
public:
    Base() {
        cout << "Base构造函数" << endl;
        callVirtual();  // 调用虚函数
    }
    
    virtual void callVirtual() {
        cout << "Base::callVirtual" << endl;
    }
    
    virtual ~Base() {
        cout << "Base析构函数" << endl;
        callVirtual();  // 调用虚函数
    }
};
 
class Derived : public Base {
public:
    Derived() {
        cout << "Derived构造函数" << endl;
        callVirtual();
    }
    
    void callVirtual() override {
        cout << "Derived::callVirtual" << endl;
    }
    
    ~Derived() {
        cout << "Derived析构函数" << endl;
        callVirtual();
    }
};
 
int main() {
    Derived d;
    // 输出:
    // Base构造函数
    // Base::callVirtual        (注意:不是Derived版本)
    // Derived构造函数
    // Derived::callVirtual
    // Derived析构函数
    // Derived::callVirtual
    // Base析构函数
    // Base::callVirtual        (注意:不是Derived版本)
}

4.2 多重继承的虚表

class Base1 {
public:
    virtual void f1() { cout << "Base1::f1" << endl; }
    virtual void f2() { cout << "Base1::f2" << endl; }
};
 
class Base2 {
public:
    virtual void g1() { cout << "Base2::g1" << endl; }
    virtual void g2() { cout << "Base2::g2" << endl; }
};
 
class Derived : public Base1, public Base2 {
public:
    void f1() override { cout << "Derived::f1" << endl; }
    void g1() override { cout << "Derived::g1" << endl; }
    virtual void h() { cout << "Derived::h" << endl; }
};
 
// Derived对象内存布局:
// +-------------+
// | vptr1       | -----> 第一个虚表(Base1相关)
// | Base1数据    |
// +-------------+
// | vptr2       | -----> 第二个虚表(Base2相关)
// | Base2数据    |
// +-------------+
// | Derived数据  |
// +-------------+

4.3 虚继承的虚表

class Base {
public:
    int base_data;
    virtual void func() { cout << "Base::func" << endl; }
};
 
class Derived1 : virtual public Base {
public:
    int d1_data;
    void func() override { cout << "Derived1::func" << endl; }
};
 
class Derived2 : virtual public Base {
public:
    int d2_data;
    void func() override { cout << "Derived2::func" << endl; }
};
 
class Final : public Derived1, public Derived2 {
public:
    int final_data;
    void func() override { cout << "Final::func" << endl; }
};
 
// Final对象会有额外的vbptr(虚基类指针)来处理虚继承

5. 虚函数的高级特性

5.1 纯虚函数和抽象类

class Interface {
public:
    // 纯虚函数
    virtual void method1() = 0;
    virtual int method2(int x) = 0;
    
    // 纯虚函数也可以有实现
    virtual void method3() = 0;
};
 
// 纯虚函数的实现(可选)
void Interface::method3() {
    cout << "Interface::method3 default implementation" << endl;
}
 
class Concrete : public Interface {
public:
    void method1() override {
        cout << "Concrete::method1" << endl;
    }
    
    int method2(int x) override {
        return x * 2;
    }
    
    void method3() override {
        Interface::method3();  // 可以调用纯虚函数的实现
        cout << "Concrete::method3" << endl;
    }
};

5.2 虚析构函数

class Base {
public:
    Base() { data = new int[100]; }
    
    // 虚析构函数非常重要!
    virtual ~Base() { 
        delete[] data;
        cout << "Base析构" << endl;
    }
    
private:
    int* data;
};
 
class Derived : public Base {
public:
    Derived() { extra = new int[200]; }
    
    ~Derived() {
        delete[] extra;
        cout << "Derived析构" << endl;
    }
    
private:
    int* extra;
};
 
int main() {
    Base* ptr = new Derived();
    delete ptr;  // 正确调用Derived和Base的析构函数
}

6. 性能分析和优化

6.1 虚函数的开销

#include <chrono>
using namespace std::chrono;
 
class Test {
public:
    // 非虚函数
    int normalFunc(int x) { return x * 2; }
    
    // 虚函数
    virtual int virtualFunc(int x) { return x * 2; }
    
    // 内联函数
    inline int inlineFunc(int x) { return x * 2; }
};
 
void performanceTest() {
    Test obj;
    Test* ptr = &obj;
    const int iterations = 100000000;
    
    // 测试非虚函数
    auto start = high_resolution_clock::now();
    for (int i = 0; i < iterations; i++) {
        ptr->normalFunc(i);
    }
    auto end = high_resolution_clock::now();
    cout << "非虚函数: " 
         << duration_cast<milliseconds>(end - start).count() 
         << "ms" << endl;
    
    // 测试虚函数
    start = high_resolution_clock::now();
    for (int i = 0; i < iterations; i++) {
        ptr->virtualFunc(i);
    }
    end = high_resolution_clock::now();
    cout << "虚函数: " 
         << duration_cast<milliseconds>(end - start).count() 
         << "ms" << endl;
}

6.2 优化技巧

// 1. 使用final避免虚函数调用
class Optimized final : public Base {
public:
    void func() override final {  // 编译器可以优化
        // ...
    }
};
 
// 2. 避免在热路径中使用虚函数
class GameObject {
public:
    // 热路径函数不要设为虚函数
    void update(float deltaTime) {
        updatePosition(deltaTime);   // 非虚
        updatePhysics(deltaTime);    // 非虚
        onSpecialEvent();            // 虚函数,偶尔调用
    }
    
protected:
    void updatePosition(float dt) { /* ... */ }
    void updatePhysics(float dt) { /* ... */ }
    virtual void onSpecialEvent() { }
};
 
// 3. 使用CRTP(奇异递归模板模式)实现静态多态
template<typename Derived>
class Base {
public:
    void interface() {
        static_cast<Derived*>(this)->implementation();
    }
};
 
class DerivedCRTP : public Base<DerivedCRTP> {
public:
    void implementation() {
        cout << "静态多态实现" << endl;
    }
};

7. 完整示例:模拟虚表机制

#include <iostream>
#include <vector>
#include <functional>
#include <map>
using namespace std;
 
// 模拟虚表的简化实现
class VirtualTable {
public:
    vector<void*> functions;
    
    void addFunction(void* func) {
        functions.push_back(func);
    }
    
    void* getFunction(int index) {
        if (index < functions.size()) {
            return functions[index];
        }
        return nullptr;
    }
};
 
// 模拟带虚函数的类
class SimulatedBase {
public:
    VirtualTable* vptr;  // 虚表指针
    int data;
    
    SimulatedBase() : data(10) {
        // 设置虚表
        static VirtualTable vtable;
        static bool initialized = false;
        if (!initialized) {
            vtable.addFunction((void*)&SimulatedBase::func1_impl);
            vtable.addFunction((void*)&SimulatedBase::func2_impl);
            initialized = true;
        }
        vptr = &vtable;
    }
    
    // 虚函数调用包装器
    void func1() {
        typedef void(*Func)(SimulatedBase*);
        Func f = (Func)vptr->getFunction(0);
        f(this);
    }
    
    void func2() {
        typedef void(*Func)(SimulatedBase*);
        Func f = (Func)vptr->getFunction(1);
        f(this);
    }
    
private:
    static void func1_impl(SimulatedBase* self) {
        cout << "Base::func1, data = " << self->data << endl;
    }
    
    static void func2_impl(SimulatedBase* self) {
        cout << "Base::func2, data = " << self->data << endl;
    }
};
 
class SimulatedDerived : public SimulatedBase {
public:
    int derived_data;
    
    SimulatedDerived() : derived_data(20) {
        // 替换虚表
        static VirtualTable vtable;
        static bool initialized = false;
        if (!initialized) {
            vtable.addFunction((void*)&SimulatedDerived::func1_impl);
            vtable.addFunction((void*)&SimulatedBase::func2_impl);
            initialized = true;
        }
        vptr = &vtable;
    }
    
private:
    static void func1_impl(SimulatedBase* self) {
        SimulatedDerived* derived = static_cast<SimulatedDerived*>(self);
        cout << "Derived::func1, data = " << derived->data 
             << ", derived_data = " << derived->derived_data << endl;
    }
};
 
int main() {
    cout << "=== 模拟虚表机制 ===" << endl;
    
    SimulatedBase base;
    SimulatedDerived derived;
    
    SimulatedBase* ptr = &base;
    ptr->func1();  // Base::func1
    ptr->func2();  // Base::func2
    
    ptr = &derived;
    ptr->func1();  // Derived::func1
    ptr->func2();  // Base::func2
    
    return 0;
}

8. 调试技巧

8.1 查看对象的虚表

// GDB调试命令
// (gdb) info vtbl object_name
// (gdb) p /a *(void**)object_ptr
 
// Visual Studio调试
// 在监视窗口中查看 *(void**)&object

8.2 运行时类型信息(RTTI)

#include <typeinfo>
 
class Base {
public:
    virtual ~Base() = default;
};
 
class Derived : public Base {};
 
void checkType(Base* ptr) {
    // 使用typeid
    cout << "类型: " << typeid(*ptr).name() << endl;
    
    // 使用dynamic_cast
    if (Derived* d = dynamic_cast<Derived*>(ptr)) {
        cout << "是Derived类型" << endl;
    } else {
        cout << "不是Derived类型" << endl;
    }
}

虚函数和虚表是C++实现运行时多态的核心机制。理解其原理有助于写出更高效、更安全的代码。