写点什么

C++ 中虚表是什么

  • 2024-03-19
    福建
  • 本文字数:1390 字

    阅读完需:约 5 分钟

定义


虚函数(Virtual Function)

  • 定义:类中使用 virtual 关键字修饰的函数 叫做虚函数

  • 语法


class Base {public:    virtual void show() { cout << "Base show" << endl; }};
复制代码


虚函数表(Virtual Function Table)


  • 定义:当类含有至少一个虚函数时,编译器会为该类创建一个虚函数表。这个表是一个编译时构建的静态数组,存储了指向类中所有虚函数的指针。如果一个派生类重写了这些函数,那么在派生类的虚表中,相应函数的指针会被更新为指向派生类中的版本。

  • 作用v-table 使得在运行时可以实现函数的动态绑定,允许通过基类的指针或引用调用正确的函数版本。


虚函数指针(Virtual Pointer)

  • 定义:每个含有虚函数的类的对象(实例化出的)会持有一个指向相应虚表的指针,这个指针通常被称为虚指针(vptr)。vptr 是对象运行时的一部分,确保了当通过基类指针调用虚函数时,能够查找到正确的函数实现。

  • 作用:在对象的生命周期开始时,构造函数会设置 vptr 以指向相应的虚函数表。如果有派生类对象,它的构造函数会更新 vptr,以指向派生类的虚函数表。这保证了通过基类的引用或指针调用虚函数也会执行最派生类的重写版本。


示例

#include <iostream>using namespace std;
class Base {public: virtual void func1() { cout << "Base::func1" << endl; } virtual void func2() { cout << "Base::func2" << endl; }};
class Derived : public Base {public: void func1() override { cout << "Derived::func1" << endl; } // func2() 继承自 Base};
void printVTable(void* obj) { cout << "vptr Address: " << obj << endl; void** vTable = *(void***)obj; cout << "VTable[0] (func1): " << vTable[0] << endl; cout << "VTable[1] (func2): " << vTable[1] << endl;}
int main() { Base* base = new Base(); Derived* derived = new Derived();
cout << "Base object:" << endl; printVTable(base);
cout << "\nDerived object:" << endl; printVTable(derived);
delete base; delete derived;
return 0;}
复制代码


程序输出如下,可以看到没用重写的 func2 函数地址是一样的。

Base object:vptr Address: 0x8c1510   VTable[0] (func1): 0x422270VTable[1] (func2): 0x4222b0
Derived object:vptr Address: 0x8c1530 VTable[0] (func1): 0x422330VTable[1] (func2): 0x4222b0
复制代码


如下图所示:



面试题


(来自 2024 腾讯实习面试)场景题:一个类 A,里面有一个打印 helloworld 的虚函数,然后类 A 会在构造函数里调用这个虚函数,此时有个类 B,继承 A,重写了这个 helloworld 虚函数,问你在创建类 B 时,会打印 A 里的 helloworld 还是 B 里的。

代码如下:

class A {public:    A() {        print();    }    virtual void print() {        cout << "A print" << endl;    }};
class B : public A {public: void print() override { cout << "B print" << endl; }};int main() { A* aTemp = new B(); delete aTemp;}
复制代码


解答:基类构造函数执行的时候,派生类的部分尚未初始化,因此调用的虚函数不会下发到派生类中。

最终会打印 A print,而不是类 B 里重写的版本


文章转载自:江水为竭

原文链接:https://www.cnblogs.com/Az1r/p/18081756

体验地址:http://www.jnpfsoft.com/?from=001

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
C++中虚表是什么_c++_快乐非自愿限量之名_InfoQ写作社区