C++虚表结构分析笔记

  • 单继承虚表结构
    #include 
    #include 
    using namespace std;
    
    class Base_1
    {
    public:
            Base_1(string n="Base_1") { name_1 = n; name_2 = name_1 + "2, yes";}
    
            virtual void b_vf_1() {}
            virtual void b_vf_2() {}
            virtual void b_vf_3() {}
            virtual void b_vf_4() {}
            virtual ~Base_1() { cout << "test ~Base_1" << endl;}
            void b_f_1() {}
    
    protected:
            string name_1;
            string name_2;
    };
    
    class Driver : public Base_1
    {
    public:
            Driver(string n="Driver"):Base_1(n) { name_1 = "dirver_test";}
            virtual void b_vf_2() {}
            void b_vf_3() {}
            void b_vf_5() {}
    
            //virtual ~Driver(){ cout << "test ~Driver" << endl ;}  
    
    private:
            string name_1;
    };
    
    int main() {
    
            Base_1 *base_1_d = new Base_1;
            Driver *driver_d = dynamic_cast (base_1_d);
            driver_d = static_cast (base_1_d);
    
            delete base_1_d;
    
            driver_d = new Driver;
            base_1_d = dynamic_cast (driver_d);
    
            delete driver_d;
    
            return 0;
    }
    
    
    
    • 虚表函数地址打印:


      C++虚表结构分析笔记_第1张图片
      基类和派生类内存结构

      C++虚表结构分析笔记_第2张图片
      基类虚表结构

      C++虚表结构分析笔记_第3张图片
      派生类虚表结构
    • 类结构和虚表拓扑:
      C++虚表结构分析笔记_第4张图片
      虚表拓扑结构
    • 结构特点:
      • 类的结构特点是:
        • 基类:虚表、类成员依次排列,成员函数在类外,静态变量和静态成员函数也在类外(不属于实例化的对象,属于类)
        • 派生类:派生类中和基类同名的函数(无论是否有virtual修饰),参数列表相同的也在虚表中,如果参数列表不同不会覆盖,有virtual修饰追加在虚表之后
      • 虚函数都在虚表中;
      • 派生类覆盖的基类的虚函数也在虚表中,eg:driver_d->b_vf_2(),driver_d->b_vf_3()
      • 派生类修改虚表的过程是在构造函数中
    • 其他:
      • 如果一个基类指针指向派生类,同时虚函数v_fun_2属于派生类,不同通过基类直接访问派生了,即使虚表中有v_fun_2的指针
  • 多重继承
    #include 
    #include 
    using namespace std;
    class Temp {
    public:
            int test_1;
            int test_2;
            int test_3;
    };
    
    class Base_1
    {
    public:
            Base_1(string n="Base_1") { name_1 = n; name_2 = name_1 + "2, yes";}
    
            virtual void b_vf_1() { cout << "Base_1 virtual function 1 " << endl; }
            virtual void b_vf_2() {}
            virtual void b_vf_3() {}
            virtual void b_vf_4() {}
            virtual ~Base_1() { cout << "test ~Base_1" << endl;}
            void b_f_1() {}
    
    protected:
            int base_1;
            string name_1;
            string name_2;
            Temp temp1;
            int base_2;
    };
    
    class Base_2
    {
    public:
            Base_2(string n="Base_2") { name_1 = n; name_2 = name_1 + "2, yes";}
    
            virtual void b_vf_1() {}
            virtual void b_vf_4() {}
            virtual void b_vf_5() { cout << "Base_2 virtual function 5 " << endl;  }
            virtual void b_vf_6() {}
            virtual ~Base_2() { cout << "test ~Base_2" << endl;}
            void b_f_1() {}
            void b_f_2() {}
    protected:
            string name_1;
            string name_2;
    };
    
    class Driver : public Base_1, public Base_2
    {
    public:
            Driver(string n="Driver"):Base_1(n) { name_1 = "dirver_test";}
            virtual void b_vf_2() {}
            void b_vf_3() {}
            virtual void b_vf_5() { cout << "Driver virtual function 5 " << endl; }
    
            //virtual ~Driver(){ cout << "test ~Driver" << endl ;}  
    
    private:
            string name_1;
    };
    
    int main() {
    
            //Base_1 *base_1_d = new Base_1;        
            //Driver *driver_d = dynamic_cast (base_1_d); 
            //driver_d = static_cast (base_1_d);
    
            //delete base_1_d;
    
            Driver *driver_d = new Driver;
            Base_1 *base_1_d = dynamic_cast (driver_d);
            Base_2 *base_2_d = dynamic_cast (driver_d);
    
            delete driver_d;
    
            return 0;
    }
    
    
    • 虚表地址打印:


      C++虚表结构分析笔记_第5张图片
      第一个虚表内容打印

      C++虚表结构分析笔记_第6张图片
      第二个虚表内容打印
    • 动态转换函数调用:

      • 动态转换后虚表内容和派生类中的虚表内容一致

      • 如果在两个基类有同名的虚函数,且参数相同,

        • 并且派生列中没有该同名虚函数的实现,如果派生类直接调用该虚函数,==会出现编译错误==
        int main() {
        
                //Base_1 *base_1_d = new Base_1;        
                //Driver *driver_d = dynamic_cast (base_1_d); 
                //driver_d = static_cast (base_1_d);
        
                //delete base_1_d;
        
                Driver *driver_d = new Driver;
                //driver_d->b_f_1();    编译不通,编译不知道调用那个基类的实现
                //driver_d->b_vf_1();   编译报错:编译器不确定第一个还是第二个基类的函数
                driver_d->b_vf_5();
        
                Base_1 *base_1_d = dynamic_cast (driver_d);
                //base_1_d->b_vf_5();   编译不通过,编译器在基类1中无法找到b_vf_5的函数声明
                base_1_d->b_vf_1();
        
                Base_2 *base_2_d = dynamic_cast (driver_d);
                base_2_d->b_vf_1();
                base_2_d->b_vf_5();
        
                delete driver_d;
        
                return 0;
        }
        
        
        C++虚表结构分析笔记_第7张图片
        两个基类中有同名的虚函数,且参数列表相同,使用派生类直接调用虚函数会编译出错
        • 如果派生类中实现同名虚函数的方法,派生类直接调用==编译不会出错==,并且动态转换成不同的基类,调用结果==是派生类的实现==
        class Driver : public Base_1, public Base_2
        {
        public:
                Driver(string n="Driver"):Base_1(n) { name_1 = "dirver_test";}
                virtual void b_vf_1() { cout << "Driver virtual function 1 " << endl;  }
                virtual void b_vf_2() {}
                void b_vf_3() {}
                virtual void b_vf_5() { cout << "Driver virtual function 5 " << endl;}
        
                //virtual ~Driver(){ cout << "test ~Driver" << endl ;}  
        
        private:
                string name_1;
        };
        
        int main() {
        
            //Base_1 *base_1_d = new Base_1;        
            //Driver *driver_d = dynamic_cast (base_1_d); 
            //driver_d = static_cast (base_1_d);
        
            //delete base_1_d;
        
            Driver *driver_d = new Driver;
            driver_d->b_vf_1();
            driver_d->b_vf_5();
        
            Base_1 *base_1_d = dynamic_cast (driver_d);
            //base_1_d->b_vf_5();   编译不通过,编译器在基类1中无法找到b_vf_5的函数声明
            base_1_d->b_vf_1();
        
            Base_2 *base_2_d = dynamic_cast (driver_d);
            base_2_d->b_vf_1();
            base_2_d->b_vf_5();
        
            delete driver_d;
        
            return 0;
        }
        
        C++虚表结构分析笔记_第8张图片
        两个基类中有同名的虚函数,且参数列表相同,派生类中有虚函数实现
      • 动态转换地址打印:派生类动态转换成基类指针之后虚表结构和派生类的虚表节结构是一致的


        C++虚表结构分析笔记_第9张图片
        派生类动态转换成基类指针之后虚表结构和派生类的虚表节结构是一致的
    • 类结构和虚表拓扑

      C++虚表结构分析笔记_第10张图片
      多重继承虚表结构拓扑

你可能感兴趣的:(C++虚表结构分析笔记)