C++中的虚函数和虚函数表

在上面一篇博客中  https://www.cnblogs.com/wphl-27/p/18111083,提到了虚函数,纯虚函数

这篇博客我想继续进一步来说一下虚函数和虚函数表

在C++中,每一个含有虚函数的类,编译器都会为它啊做出一个虚函数表(通常叫做 vtable), 这个虚函数表里面的每个元素都是函数指针,每个元素(函数指针)指向一个虚函数的地址.

除此之外,编译器还会为这种含有虚函数的类,添加上一个成员变量,这个成员变量是一个指向它的虚函数表的指针(通常称为 vptr). 我们来看下面这个例子

 

class Class1  {
public :
    data1;
    data2;
    memfunc();
    virtual vfunc1();
    virtual vfunc2();
    virtual vfunc3();
};

这个Class1 ,它里面包括3个虚函数,我们来看看这个类在内存中空间

我们可以看到,它自动增加了一个成员变量 vptr, 这是一个指针,可以看到它指向的是Class1的虚函数表vtable, 这个虚函数表中有3个元素,是3个函数指针,它们分别指向Class1的三个虚函数的地址

当有一个派生类来继承基类Class1时,它会继承基类的虚函数表(以及其他所有可以继承的成员),  派生类中同样有这个新增的成员变量 vptr, 它同样指向派生类的虚函数表.

当我们在派生类中改写某个虚函数时,它继承下来的虚函数表就受了影响,虚函数表中对应的这个虚函数的函数指针,指向的地址将不再是基类的函数地址,而是改写后的派生类中该虚函数的函数地址

我们来看个例子:

class Class2 : public Class1 {
public :
    data3;
    memfunc();
    virtual vfunc2();
};

它的内存空间是这样的

可以看到Class2的虚函数表vtable中,它的第二个函数指针指向的是Class2::vfunc2(), 而不再是基类的Class1::vfunc1(), 也就是说它存的是Class2函数自己的重写后的vfun2函数的地址

所以一个「指向Class1所生对象」的指针,所调用的 vfunc2 就是 Class1::vfunc2,而一个「指向Class2 所生对象」的指针,所调用的 vfunc2 就是 Class2::vfunc2。

这也就是说我们在上篇博客 

C++中基类指针指向派生类对象  中提到的动态联编机制。 动态联编,在运行时,而不是编译时,会根据虚函数表,来做出正确的选择

 

posted on 2024-04-03 19:09  新西兰程序员  阅读(2)  评论(0编辑  收藏  举报