打印虚函数表的地址

1,016 阅读1分钟

C++的多态是通过虚函数来实现的,虚函数机制通过虚函数表来实现动态绑定。

如果一个类本身或者其父类包含虚函数,那么编译器会为类对象的头部额外生成一个指针,用于指向该类维护的虚函数表。虚函数表中维护着来自父类和自身的虚函数。

内存布局示意图:

// 包含虚函数的类
class VirtualBase {
public:
    virtual void fun1()
    {
        std::cout << "VirtualBase fun1" << std::endl;
    }
};

class VirtualChild : public VirtualBase {
public:
    virtual void fun2()
    {
        std::cout << "VirtualChild fun2" << std::endl;
    }

    virtual void fun3()
    {
        std::cout << "VirtualChild fun3" << std::endl;
    }
};

通过虚函数表,调用虚函数

typedef void(*FUNC) ();

void PrintFunc(int* func)
{
    FUNC fun = (FUNC) *func;
    fun();
}

int main() {
    VirtualChild* child = new VirtualChild();
    
    // 将child的地址转换成long long型,因为在64位编译器上面,指针占用8个字节
    // child是指向虚函数表的指针的地址
    long long* tmp = (long long*) child;	
    
    // 解引用,得到虚函数表的地址
    long long* vptr = (long long*)(*tmp);
	
    // 虚函数表中第一个方法,继承于父类的虚函数fun1
    FUNC fun1 = (FUNC) *vptr;
    
    // 虚函数表中第二个方法
    FUNC fun2 = (FUNC) *(vptr + 1);
    
    // 虚函数表中第三个方法
    FUNC fun3 = (FUNC) *(vptr + 2);
    fun1();
    fun2();
    fun3();
}

// 输出结果
VirtualBase fun1
VirtualChild fun2
VirtualChild fun3