zoukankan      html  css  js  c++  java
  • 由剑指offer引发的思考——对象中虚函数指针的大小

    先看一个简单的问题:

    一、定义一个空的类型,对于其对象我们sizeof其大小,是1字节。因为我们定义一个类型,编译器必须为其分配空间,具体分配多少是编译器决定,vs是1字节,分配在栈区。

          那,这一个字节会被初始化吗?

    举个例子:

    #include<iostream>
    class parent{
    
    };
    int main() {
        parent my_par;
        int a = 0;
        std::cout << sizeof(my_par) << " "<< &my_par<<" "<<&a;
        while (1);
        return 0;
    }

    其输出:

       

    我们查看内存,看得到都初始化为:CC CC CC CC                                       

    多调试几次,每次地址都不一样,但是内存值都是CC。为什么都是CC?

     因为0xCC对应的是INT3断点,简单地说就是将要断下的指令地址处的第一个字节设置为0xCC,软件执行到0xCC(对应汇编指令INT3)时,会触发异常代码为EXCEPTION_BREAKPOINT的异常。这样我们的调试程序就能够接收到这个异常,然后进行相应的处理。具体.......所以,我们写的是异常代码,实际工作中空类型又有什么意义呢?具体会设计编译器逆向工程,有机会可以看看。

    回到我们标题:

    二、虚函数的问题

    1. 当类中声明虚函数时,编译器会在类中生成一个虚函数表,若子类自己有虚函数也会生成一个虚函数表
    2. 虚函数表是一个存储 类的virtual成员函数指针的数据结构;
    3. 当存在虚函数时,每个对象都有一个指向虚函数表的指针(类本身没有指针,有一个编译器维护的虚函数表。对象有虚函数指针,我们sizeof是测的是对象所占内存)
    4. 若一个对象继承于两个都有虚函数的父类,他要维护两个虚函数指针;
    5. 虚函数指针存在于对象实例中最前面的位置;
    #include <iostream>
    using namespace std;
     
    class Base1{
        virtual void fun1(){}
        virtual void fun11(){}
    public:
        virtual ~Base1();
    };
     
    class Base2{
        virtual void fun2(){}
    };
     
    class DerivedFromOne: public Base2
    {
        virtual void fun2(){}
        virtual void fun22(){}
    };
     
    class DerivedFromTwo: public Base1, public Base2      //多继承
    {
        virtual void fun3(){}
    };
     
    void main()
    {
    Base2 my_base; cout
    << "sizeof Base1 " << sizeof(Base1) << "输出vptb"<<(int*)*(int*)(&my_base)<< endl;//太复杂了,以后再说。 cout << "sizeof Base2" << sizeof(Base2) << endl; cout << "sizeof FromOne " << sizeof(DerivedFromOne) << endl; cout << "sizeof FromTwo " << sizeof(DerivedFromTwo) << endl; system("pause") }

     输出:

     

    可以看出:

    1、每个单继承,对象都有一个vptr指针;多继承,对象就会有多个虚函数指针指向父类的虚函数表。虚函数表不占栈内存,由编译器维护,在代码区?我们测的是对象的内存

    2、Base2的对象的地址,就是vptr指向的虚函数表的地址,可以打开内存查看。这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。

        

  • 相关阅读:
    Spring 在xml配置里配置事务
    Spring事务的传播行为
    Spring 自动装配;方法注入
    Spring 依赖注入(一、注入方式)
    Spring事务
    C3P0使用详解
    php 解析json失败,解析为空,json在线解析器可以解析,但是json_decode()解析失败(原)
    Linux下的crontab定时执行任务命令详解
    crontab 常见 /dev/null 2>&1 详解
    实体字符转换,同样变量密码加盐MD5后生成的加密字符串不同解决办法 (原)
  • 原文地址:https://www.cnblogs.com/huangfuyuan/p/9142545.html
Copyright © 2011-2022 走看看