• C++多重继承虚表的内存分布


    接前面虚表的内存分布,今天重点看多重继承的虚表内存分布,简单的说,继承几个类便有几个虚表,如下代码

    class Drive : public Base1, public Base2, public Base3 {
    public:
        virtual void fd() { cout << "Drive::fd" << endl; }
        virtual void gd() { cout << "Drive::gd" << endl; }
    };

    则虚表有3个,如下图所示:

    添加更多的测试代码:

    // trytest.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    
    #include <WTypes.h>
    #include < iostream >
    
    using namespace std;
    
    class Base1 {
        virtual void f() { cout << "Base1::f" << endl; }
        virtual void g() { cout << "Base1::g" << endl; }
    };
    
    class Base2 {
        virtual void f() { cout << "Base2::f" << endl; }
        virtual void g() { cout << "Base2::g" << endl; }
    };
    
    class Base3 {
        virtual void f() { cout << "Base3::f" << endl; }
        virtual void g() { cout << "Base3::g" << endl; }
    };
    
    class Drive : public Base1, public Base2, public Base3 {
    public:
        virtual void fd() { cout << "Drive::fd" << endl; }
        virtual void gd() { cout << "Drive::gd" << endl; }
    };
    
    typedef void(*Fun)(void);
    
    int main() {
        Drive objDrive;
        cout << "Size is = " << sizeof(objDrive) << endl; 
    
        Fun pFun = NULL;
    
        cout<<"sizeof(int)="<<sizeof(int)<<endl;
        cout<<"sizeof(int*)="<<sizeof(int*)<<endl;
    
        // 调用Base1的第一个虚函数
        pFun = (Fun)*((int*)*(int*)((int*)&objDrive + 0) + 0);
        pFun();
        // 调用Base1的第二个虚函数
        pFun = (Fun)*((int*)*(int*)((int*)&objDrive + 0) + 1);
        pFun();
        cout << "Address of virtual pointer 1 " << (int*)(&objDrive + 0) << endl;
        cout << "Value at virtual pointer i.e. Address of virtual table " 
            << (int*)*(int*)((int*)&objDrive + 0) << endl;
        cout << "Information about VTable 1" << endl; 
        cout << "Value at 1st entry of VTable " 
            << (int*)*((int*)*(int*)((int*)&objDrive + 0) + 0) << endl; 
        cout << "Value at 2nd entry of VTable " 
            << (int*)*((int*)*(int*)((int*)&objDrive + 0) + 1) << endl; 
    
    
    
        // 调用Base2的第一个虚函数
        pFun = (Fun)*((int*)*(int*)((int*)&objDrive + 1) + 0);
        pFun();
        // 调用Base2的第二个虚函数
        pFun = (Fun)*((int*)*(int*)((int*)&objDrive + 1) + 1);
        pFun();
        cout << "Address of virtual pointer 2 " << (int*)((int*)&objDrive + 1) << endl;
        cout << "Value at virtual pointer i.e. Address of virtual table " 
            << (int*)*(int*)((int*)&objDrive + 1) << endl;
        cout << "Information about VTable 2" << endl; 
        cout << "Value at 1st entry of VTable " 
            << (int*)*((int*)*(int*)((int*)&objDrive + 1) + 0) << endl; 
        cout << "Value at 2nd entry of VTable " 
            << (int*)*((int*)*(int*)((int*)&objDrive + 1) + 1) << endl; 
    
        // 调用Base3的第一个虚函数
        pFun = (Fun)*((int*)*(int*)((int*)&objDrive + 2) + 0);
        pFun();
        // 调用Base3的第二个虚函数
        pFun = (Fun)*((int*)*(int*)((int*)&objDrive + 2) + 1);
        pFun();
        cout << "Address of virtual pointer 3 " << (int*)((int*)&objDrive + 2) << endl;
        cout << "Value at virtual pointer i.e. Address of virtual table " 
            << (int*)*(int*)((int*)&objDrive + 2) << endl;
        cout << "Information about VTable 3" << endl; 
        cout << "Value at 1st entry of VTable " 
            << (int*)*((int*)*(int*)((int*)&objDrive + 2) + 0) << endl; 
        cout << "Value at 2nd entry of VTable " 
            << (int*)*((int*)*(int*)((int*)&objDrive + 2) + 1) << endl; 
    
        // 调用派生类的第一个虚函数
        pFun = (Fun)*((int*)*(int*)((int*)&objDrive + 0) + 2);
        pFun();
        // 调用派生类的第二个虚函数
        pFun = (Fun)*((int*)*(int*)((int*)&objDrive + 0) + 3);
        pFun();
        cout << "Value at 3rd entry of VTable " 
            << (int*)*((int*)*(int*)((int*)&objDrive + 0) + 2) << endl; 
        cout << "Value at 4th entry of VTable " 
            << (int*)*((int*)*(int*)((int*)&objDrive + 0) + 3) << endl; 
    
     
        //明确多重继承中虚函数的内存位置
        cout <<"Address at 1st entry of VTable "
            << (int*)*((int*)&objDrive + 0) + 0 << endl; 
    
        cout <<"Address at 2nd entry of VTable "
            << (int*)*((int*)&objDrive + 0) + 1 << endl; 
    
        cout <<"Address at 3rd entry of VTable "
            << (int*)*((int*)&objDrive + 0) + 2 << endl; 
    
        cout <<"Address at 4th entry of VTable "
            << (int*)*((int*)&objDrive + 0) + 3 << endl; 
    
        pFun = (Fun)*((int*)*((int*)&objDrive + 0) + 0);
        pFun();
    
        pFun = (Fun)*((int*)*((int*)&objDrive + 0) + 1);
        pFun();
    
        pFun = (Fun)*((int*)*((int*)&objDrive + 0) + 2);
        pFun();
    
        pFun = (Fun)*((int*)*((int*)&objDrive + 0) + 3);
        pFun();
    
    
        return 0;
    }

    内存分布如下所示:

  • 相关阅读:
    让Windows Server 2008 + IIS 7+ ASP.NET 支持10万个同时请求
    C#多线程锁定全局变量
    ASP.NET 防止F5刷新页面按钮重复提交
    子线程调用窗体控件
    asp.net 转成XML后在SQL操作XML的值
    Sql中字符串的循环截取(用循环实现输入键串能输出值串)
    大数据量分页存储过程
    函数相关概念,及练习
    js循环(while循环,do while循环,for循环)相关知识点及练习
    parseInt()和Number()的应用区别
  • 原文地址:https://www.cnblogs.com/luhouxiang/p/3215343.html
Copyright © 2020-2023  润新知