一、概念解析
C++ 中,虚函数表(Virtual Function Table)用于实现多态,是实现C++类为基本的Object-oriented思想的重要工具之一。虚函数表是一个数据结构,存储着该类对象中所有虚函数的地址信息,使得在代码执行中可以正确地调用到当前对象所属的类的实现。
二、实现原理
C++ 虚函数表的实现原理是通过将虚函数的地址存储在虚函数表中,在函数调用时通过虚函数表中的地址来找到正确的函数并进行调用。
class Base { public: virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } }; class Derived : public Base { public: void foo() override { cout << "Derived::foo()" << endl; } }; int main() { Base* ptr = new Derived(); ptr->foo(); // Derived::foo() ptr->bar(); // Base::bar() return 0; }
在上述代码中,由于虚函数表中存储了 Derived::foo() 的地址信息,所以当执行 ptr->foo() 时会执行 Derived::foo(),而在虚函数表中找不到 Derived::bar() 的地址,则会执行Base::bar()。
三、虚函数表的构造与析构
虚函数表的构造和析构涉及对象的创建和销毁,C++ 约定虚函数表与对象一起构造和销毁。
当定义一个类时,编译器会自动生成该类的虚函数表并初始化,将每个虚函数的地址存储在该类的虚函数表中。
class Base { public: virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } }; class Derived : public Base { public: void foo() override { cout << "Derived::foo()" << endl; } }; int main() { Base* ptr = new Derived(); ptr->foo(); // Derived::foo() delete ptr; return 0; }
在上述代码中,Derived 对象被创建后其虚函数表会存放在该对象的内存的开头,当删除 Derived 对象时也会清除相应的虚函数表。
四、虚函数表与多重继承
在多重继承中,一个对象可能会有多个虚函数表。C++ 会对这些虚函数表进行处理使得存储在每个虚函数表中的函数地址不发生冲突。
class A { public: virtual void foo() { cout << "A::foo()" << endl; } }; class B { public: virtual void bar() { cout << "B::bar()" << endl; } }; class C : public A, public B { public: void foo() override { cout << "C::foo()" << endl; } void bar() override { cout << "C::bar()" << endl; } }; int main() { C* ptr = new C(); A* ptr_a = static_cast(ptr); B* ptr_b = static_cast (ptr); ptr_a->foo(); // C::foo() ptr_b->bar(); // C::bar() delete ptr; return 0; }
上述代码中 C 类继承了 A 和 B 两个类,在创建 C 对象时,该对象会有两个虚函数表,存储各自的虚函数的地址。在使用 static_cast 将 C 对象转换为 A 和 B 指针时,会调用各自虚函数表中存储的地址来执行相应的函数。