C++ 虚函数表

虚函数表是实现多态特性重要的数据结构. 在中用vptr成员指针保存虚函数表的内存地址. 虚函数表保存虚函数的地址, 用于动态查找对象真实类型关联的方法. vptr一般保存于对象内存布局的头几个字节(指针大小). 下面是获取虚函数表虚函数的例子:

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

class derive : public base {
  public:
    void show() { std::cout << "show_derive" << std::endl; };
};

// 获取vptr的值
static void *_get_addr(void *obj, size_t offset) {
    size_t ptrsize = sizeof(void *);
    return *(void**)((char *)obj + offset * ptrsize);
}

using func_t = void (*)();

// 获取vtable中, 成员(虚函数指针)的值
static func_t _get_func_addr(void *vptr, size_t offset) {
    size_t ptrsize = sizeof(void *);
    return (func_t)(*(void**)((char *)vptr + offset * ptrsize));
}

int main(void) {
    derive der;
    base *d = &der;

    void *vptr = _get_addr(d, 0); // 获取对象中vptr的值
    std::cout << "vptr: " << vptr << std::endl;

    func_t der_show_addr = _get_func_addr(vptr, 0);
    der_show_addr();

    func_t der_on_base_addr = _get_func_addr(vptr, 1);
    der_on_base_addr();
}

输出:

vptr: 0x561943555d78
show_derive
on_base

从上面的例子可以得出:

  • vptr成员保存在对象头几个字节(指针大小).
  • 派生类实现的虚函数在虚函数表中会覆盖基类的虚函数, 没有实现的虚函数则继承自基类.

如果觉得有帮助,可以扫描右边的微信打赏码支持一下.

Leave a Reply

Your email address will not be published. Required fields are marked *