虚函数(Virtual)

在结构体封装的函数前面加上Virtual

class Base            
{            
public:            
    void Function_1()            
    {            
        printf("Function_1...\n");            
    }            
    virtual void Function_2()            
    {            
        printf("Function_2...\n");            
    }            
};

注:通过对象调用虚函数时,虚函数与普通函数都是E8 Call(直接call)。通过指针调用时虚函数是FF Call(间接call)

虚函数地址表

当在类中的成员有虚函数时,类的大小会多四个字节(无论有多少个虚函数,只多四字节)。
这个多出来的四字节(this指针)地址指向的是虚函数地址表的首地址。
总结


作业一(单继承无函数覆盖)

#include<stdio.h>
struct Base
{
public:
    virtual void Function_1()
    {
        printf("Base:Function_1...\n");
    }
    virtual void Function_2()
    {
        printf("Base:Function_2...\n");
    }
    virtual void Function_3()
    {
        printf("Base:Function_3...\n");
    }
};
struct Sub :Base
{
public:
    virtual void Function_4()
    {
        printf("Sub:Function_4...\n");
    }
    virtual void Function_5()
    {
        printf("Sub:Function_5...\n");
    }
    virtual void Function_6()
    {
        printf("Sub:Function_6...\n");
    }
};

void TestMethod()
{
    //查看 Sub 的虚函数表                
    Sub base;
    //对象的前四个字节就是虚函数表                
    printf("base 的虚函数表地址为:%x\n", *(int*)&base);
    //通过函数指针调用函数,验证正确性                
    typedef void(*pFunction)(void);
    pFunction pFn;
    for (int i = 0; i < 6; i++)
    {
        int temp = *((int*)(*(int*)&base) + i);
        pFn = (pFunction)temp;
        pFn();
    }
}
int main() {
    TestMethod();
    return 0;
}

一

作业二(单继承,有覆盖)

#include<stdio.h>
struct Base
{
public:
    virtual void Function_1()
    {
        printf("Base:Function_1...\n");
    }
    virtual void Function_2()
    {
        printf("Base:Function_2...\n");
    }
    virtual void Function_3()
    {
        printf("Base:Function_3...\n");
    }
};
struct Sub :Base
{
public:
    virtual void Function_1()
    {
        printf("Sub:Function_1...\n");
    }
    virtual void Function_2()
    {
        printf("Sub:Function_2...\n");
    }
    virtual void Function_6()
    {
        printf("Sub:Function_6...\n");
    }
};

void TestMethod()
{
    //查看 Sub 的虚函数表                
    Sub base;
    //对象的前四个字节就是虚函数表                
    printf("base 的虚函数表地址为:%x\n", *(int*)&base);
    //通过函数指针调用函数,验证正确性                
    typedef void(*pFunction)(void);
    pFunction pFn;
    for (int i = 0; i < 4; i++)
    {
        int temp = *((int*)(*(int*)&base) + i);
        pFn = (pFunction)temp;
        pFn();
    }
}
int main() {
    TestMethod();
    return 0;
}

二

总结:子类会继承父类虚函数。子类和父类虚函数重复,颠覆继承、

最后修改:2021 年 02 月 06 日
如果觉得我的文章对你有用,请随意赞赏