欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++虚函数表的应用详解

程序员文章站 2022-06-22 19:33:24
我们知道在C++中要调用类的私有方法,我们可以使用友员(friend)的方式。但其实如果我们知道类的定义,完全可以根据该类对象的内存布局来直接调用它的私有函数。 本文作为&ldq...

我们知道在C++中要调用类的私有方法,我们可以使用友员(friend)的方式。但其实如果我们知道类的定义,完全可以根据该类对象的内存布局来直接调用它的私有函数。

本文作为“C++虚函数实现原理”的后续文章,并不打算介绍类的内存布局,本文只介绍如何使用虚函数表的方式来调用该类的私有虚函数。

现有如下Test类,提供了一个私有虚函数virtual void Func():


class Test {
public:
    Test() {

    }

    virtual~ Test() {

    }

private:
    virtual void Func() {
        printf("Private Function\n");
    }
};

现在我们使用虚函数表来调用Func成员函数:

typedef void(*PFN_Func)();

int main()
{
    Test t;
    unsigned long **VirtualTable = (unsigned long **)(&t);
    unsigned long FuncAddr = VirtualTable[0][1];

    PFN_Func pfnFunc = (PFN_Func)FuncAddr;
    if (pfnFunc) {
        pfnFunc();
    }

    return 0;
}

我们知道虚函数表其实就是一个二维数组。因为示例中的Test类没有继承于其他类,所以第一维只有一个元素;又因Test类有2个虚函数,故第二维有2个元素,且Func排在第二个,所以用VirtualTable[0][1]来取Func函数地址。

因为该示例运行在MSVC编译器环境,所以默认认为虚函数表位于类对象内存布局的起始位置,故直接使用了unsigned long **VirtualTable = (unsigned long **)(&t);。

严谨的做法应该是先判断虚函数表是否位于内存布局起始位置。