zoukankan      html  css  js  c++  java
  • 深入理解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。而虚函数表的情况一如我们之前讨论。再细看,我们发现虚基类并不作为继承类的一部分,而是由虚类表来找到。

  • 相关阅读:
    函数指针
    系统学习爬虫_2_urllib
    系统学习爬虫_1_爬虫基本原理讲解
    机器学习_集成算法与随机森林_案例实战:泰坦尼克获救预测
    机器学习_决策树及实战
    数据库_8_SQL基本操作——数据操作
    数据库_7_SQL基本操作——表操作
    数据库_6_SQL基本操作——库操作
    数据库_5_MySQL数据库介绍
    数据库_4_SQL介绍
  • 原文地址:https://www.cnblogs.com/programmer-kaima/p/4909275.html
Copyright © 2011-2022 走看看