C++中虚表是什么意思(概念及示例)

 更新时间:2024年03月19日 08:55:45   作者:江水为竭  
虚函数表,以及虚函数指针是实现多态性(Polymorphism)的关键机制,这篇文章主要介绍了C++中虚表是什么意思(概念及示例),需要的朋友可以参考下

虚函数表,以及虚函数指针是实现多态性(Polymorphism)的关键机制。多态性允许我们通过基类的指针或引用来调用派生类的函数

定义

虚函数(Virtual Function)

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

  • 语法

highlighter- cpp

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

虚函数表(Virtual Function Table)

  • 定义:当类含有至少一个虚函数时,编译器会为该类创建一个虚函数表。这个表是一个编译时构建的静态数组,存储了指向类中所有虚函数的指针。如果一个派生类重写了这些函数,那么在派生类的虚表中,相应函数的指针会被更新为指向派生类中的版本。
  • 作用v-table使得在运行时可以实现函数的动态绑定,允许通过基类的指针或引用调用正确的函数版本。

虚函数指针(Virtual Pointer)

  • 定义:每个含有虚函数的类的对象(实例化出的)会持有一个指向相应虚表的指针,这个指针通常被称为虚指针(vptr)。vptr是对象运行时的一部分,确保了当通过基类指针调用虚函数时,能够查找到正确的函数实现。
  • 作用:在对象的生命周期开始时,构造函数会设置vptr以指向相应的虚函数表。如果有派生类对象,它的构造函数会更新vptr,以指向派生类的虚函数表。这保证了通过基类的引用或指针调用虚函数也会执行最派生类的重写版本。

示例

highlighter- cpp

#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函数地址是一样的。

highlighter- apache

Base object:
vptr Address: 0x8c1510   
VTable[0] (func1): 0x422270
VTable[1] (func2): 0x4222b0
Derived object:
vptr Address: 0x8c1530   
VTable[0] (func1): 0x422330
VTable[1] (func2): 0x4222b0

如下图所示:

面试题

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

代码如下:

highlighter- arduino

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 里重写的版本

到此这篇关于C++中虚表是什么的文章就介绍到这了,更多相关C++虚表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++中构造函数的初始化顺序说明

    C++中构造函数的初始化顺序说明

    C++构造函数调用遵循基类→成员对象→派生类顺序,虚函数在构造中静态绑定,完成后动态绑定,拷贝构造在初始化、赋值及容器操作时调用,RVO优化可能避免拷贝,虚函数重写自子类起生效,不追溯基类
    2025-07-07
  • C++中头文件的概念与基本编写方法

    C++中头文件的概念与基本编写方法

    这篇文章主要介绍了C++中头文件的概念与基本编写方法,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-12-12
  • Qt实现定时器的两种方法分享

    Qt实现定时器的两种方法分享

    这篇文章主要为大家详细介绍了Qt中实现定时器的两种不同方法,文中的示例代码讲解详细,对我们了解Qt有一定的帮助,感兴趣的可以跟随小编一起学习一下
    2022-11-11
  • C++函数返回双值的几种方法

    C++函数返回双值的几种方法

    本文介绍了在C++和Qt开发中返回两个double值的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-01-01
  • C语言求幂计算的高效解法

    C语言求幂计算的高效解法

    这篇文章主要介绍了C语言求幂计算的高效解法,分别演示了求幂运算与整数次方的解法,具有不错的参考借鉴价值,需要的朋友可以参考下
    2014-09-09
  • C++结合OpenCV实现RRT算法(路径规划算法)

    C++结合OpenCV实现RRT算法(路径规划算法)

    这篇文章主要介绍了C++结合OpenCV实现RRT算法,RRT算法整体框架主要分为rand、near、new三点的建立和near与new之间的安全性检查,需要的朋友可以参考下
    2022-05-05
  • C/C++程序开发中实现信息隐藏的三种类型

    C/C++程序开发中实现信息隐藏的三种类型

    这篇文章主要介绍了C/C++程序开发中实现信息隐藏的三种类型的相关资料,需要的朋友可以参考下
    2016-02-02
  • C语言中二级指针的实例详解

    C语言中二级指针的实例详解

    这篇文章主要介绍了C语言中二级指针的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握理解二级指针的知识,需要的朋友可以参考下
    2017-10-10
  • C++详细实现红黑树流程详解

    C++详细实现红黑树流程详解

    今天我要跟大家介绍二叉搜索树中的另一颗树——红黑树,它主要是通过控制颜色来控制自身的平衡,但它的平衡没有AVL树的平衡那么严格
    2022-06-06
  • QT基于TCP实现文件传输系统

    QT基于TCP实现文件传输系统

    这篇文章主要为大家详细介绍了QT基于TCP实现文件传输系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08

最新评论