• 深入理解C++虚函数表


      虚函数表是C++类中存放虚函数的一张表,理解虚函数表对于理解多态很重要。

      本次使用的编译器是VS2013,为了简化操作,不用去操作函数指针,我使用到了VS的CL编译选项来查看类的内存布局。

      CL使用方法:

      (1)在开始菜单中的vs目录下打开"Visual Studio Tools"目录,找到"VS2013 开发人员命令提示",打开它;

      (2)将你要编译的文件放到该命令行对应的文件夹中。

      (3)输入cl "文件名" /d1reportSingleClassLayout"类名"

      (具体的使用方法可以参考以下博客:http://www.cnblogs.com/dsky/archive/2012/02/07/2340984.html)

      例子:

    #include <iostream>
    using namespace std;
    
    class C {
    public:    
        int a;
        int b;
    };
    
    int main() {
        return 0;
    }

      输出结果:

      (1)单个类的虚函数表

    class C {
    public:    
        virtual void foo() {}
        int m;
    };

      结果分析:可以看见虚表处于类的最开始处,这是为了提高效率和正确查找虚函数。

      (2)单继承

    class Base {
    public:
        virtual void v1() {}
        int b;
    };
    
    class Derived : public Base {
    public:    
        virtual void v2() {}
        int d;
    };

      结果分析:在类Derived的最前面是类Base,与我们所预期的一样。虚表并不是Base和Derived都有,而是只有Base有,Derived中的虚函数放在了Base里的虚表中。

      (3)单继承 + 覆盖

    class Base {
    public:
        virtual void v1() {}
        int b;
    };
    
    class Derived : public Base {
    public:    
        virtual void v1() {}
        virtual void v2() {}
        int d;
    };

      结果分析:我们在Derived中覆盖了Base的v1,从结果可以看出虚表中原来的Base::v1变为了Derived::v1

      (4)多继承

    class Base1 {
    public:
        virtual void v1() {}
        int b1;
    };
    
    class Base2 {
    public:    
        virtual void v2() {}
        int b2;
    };
    
    class Derived : public Base1, public Base2 {
    public:    
        virtual void v3() {}
        int d;
    };

      结果分析:两个基类各自有自己的虚表,而Derived的虚函数放在了第一张虚表中。

      (5)虚继承

    class VBase {
    public:
        virtual void vb1(){}
        int vb;
    };
    
    class Base1 : virtual public VBase {
    public:
        virtual void v1() {}
        int b1;
    };
    
    class Base2 : virtual public VBase {
    public:    
        virtual void v2() {}
        int b2;
    };
    
    class Derived : public Base1, public Base2 {
    public:    
        virtual void v3() {}
        int d;
    };

      结果分析:虚继承后,基类中多了一张虚类表(vbtable),该虚类表记录的是到虚类的偏移量,比如4+24 = 28。而虚函数表的情况一如我们之前讨论。再细看,我们发现虚基类并不作为继承类的一部分,而是由虚类表来找到。

  • 相关阅读:
    【Javascript】JS单例模式的简单实现
    【Javascript】Javascript中如何判断变量是数组类型
    买卖股票的最佳时机 II
    只出现一次的数字
    删除排序数组中的重复项
    两数之和
    Android系统中Fastboot和Recovery所扮演的角色。
    虚函数、纯虚函数、抽象类、接口 (Java_C++_C#)
    关于cmd中执行命令路径包含空格的解决办法
    Windows API 编程学习记录<三>
  • 原文地址:https://www.cnblogs.com/programmer-kaima/p/4909275.html
Copyright © 2020-2023  润新知