zoukankan      html  css  js  c++  java
  • 深入探索C++对象模型(1) 关于对象(思维导图)

    关于对象

    通过上面整个关于对象的基础知识框架,我们来分析两个例子,看一下在内存中,对象究竟长什么样。

     

    Demo1:C++对象模型的内存布局

    class Point {
    public:
        Point( float xval );
        virtual ~Point();
    
        float x() const;
        static int PointCount();
    
    protected:
        virtual ostream&
            print( ostream &os ) const;
        float _x;
        static int _point_count;
    ]};

    对于上面这个Point类,在内存中是怎么布置起来的呢?

    1. 我们将这个问题分为几个小问题,考虑篇幅,答案直接给在问题后面:
    2. 构造函数存放在什么位置?(答:类外或者类内,由构造函数的定义位置所决定)
    3. 析构函数存放在什么位置?(答:虚函数表中的一个表项指向,即指针指向)
    4. nonstatic member function,这里为x()函数,存放在什么位置?(答:由构造函数的定义位置所决定)
    5. static member function,这里为PointCount(),存放在什么位置?(答:类外)
    6. 虚函数放在什么位置?(答:虚函数表中的一个表项指向,即指针指向)
    7. nonstatic data member放在什么位置?(答:类内)
    8. static data member放在什么位置?(答:类外)

    根据以上这些问题,我们可以给出如下的对象布局方式:

    image

    由此可见,对于虚函数来说,它们由一个虚函数表统一管理,而在对象中只存放指向该虚函数表的指针。

     

    Demo2:子类的对象布局

    在Demo1中,我们了解了一个对象在内存中是如何存放的,现在我们给它加上继承机制

    即父类派生的子类的对象在内存中是如何布局的

    看下面这段代码:

    class ZooAnimal {
    public:
        ZooAnimal();
        virtual ~ZooAnimal();
        // ... 
        virtual void rotate();
    
    protected:
        int loc;
        String name;
    };
    
    
    class Bear : public ZooAnimal {
    public:
        Bear();
        ~Bear();
        // ...
        void rotate();
        virtual void dance();
        //....
    protected:
        enum Dances { ... };
    
        Dances dances_known;
        int cell_block;
    };
    
    class Panda : public Panda {
    // ........
    };

    这里使用了二层继承 ZooAnimal <--- Bear <--- Panda.

    思考下面这段代码,在内存中的布局是怎样的呢?

    {
        ZooAnimal za;          // 对象分配在栈上    
        ZooAnimal *pza;       // 指针分配在栈上
        
        Bear b;        //对象分配在栈上
        Panda *pp = new Panda    // pp指针分配在栈上,对象new在堆中
        
        pza = &b;
    }

    根据注释上所说,我们在内存中的相应的位置,按顺序设想一下该段代码执行后内存中栈和堆的布局情况:

    image

    这个图中并没有考虑栈和堆的增长方向不同的因素,所以这里也就不深究。

    栈中发生了什么很容易看得出,我们着重看一下在堆中的Panda对象的内存分布:

    发现Panda对象被分成了三个部分,Panda对象 = Panda对象自己的一部分+Bear对象部分(Bear对象部分 = Bear对象自己的一部分 +基类ZooAnimal部分)

    在栈中的Bear对象也是同样的道理。

    由此图,我们大致了解了子类在内存中的布局。

    因此,父类和子类之间的类型转换,即多态的实现,就可以认为是指针的覆盖范围的变换,而对内存布局没有影响。

     

    小结:

    简单探讨了一下对象在内存中的布局问题,以及如果通过布局来实现继承和多态的。

     

    如果不正确的地方欢迎指正。

    参考资料:

    《深入理解C++对象模型》

  • 相关阅读:
    使用jedis操作redis常用方法
    PostgreSQL下安装pg_stat_statements
    redis+keepalived安装
    eclipse离线安装Activiti Designer插件
    PostgreSQL下安装pg_stat_statements
    mysql设置索引
    使用appium在android7.0真机上测试程序时报错command failed shell “ps ‘uiautomator’”的解决方式
    appium--adb版本过低
    appium报错--版本不匹配
    win7提示不是正版桌面变黑
  • 原文地址:https://www.cnblogs.com/suzhou/p/deepinobj01.html
Copyright © 2011-2022 走看看