• 《深度探索C++对象模型》阅读笔记 第一章 关于对象


    C++对象模型

    C++类包含两种数据成员:静态数据成员和非静态数据成员;同时包含成员函数,静态函数和虚函数三种成员函数
    在此模型中,Nonstatic data members被配置于每一个 class object 之内,static data members则被存放在所有的 class object 之外. staticnonstatic function members也被放在所有的class object 之外. Virtual functions 则由虚表机制实现,class 里保存着一个指向虚表的指针,虚表中存放着指向虚函数的函数指针。
    在这里插入图片描述

    每一个class所关联的type_info object(用以支持 runtime type identification,RTTI)也经由 virtual table 被指出来,通常是放在表格的第一个slot处。

    这个模型的主要优点在于它的空间和存取时间的效率;主要缺点则是,如果应用程序代码本身未曾改变,但所用到的 class objectsnonstatic data members有所修改(可能是增加、移除或更改),那么那些应用程序代码同样得重新编译,关于这点,前述的双表格模型就提供了较大的弹性,因为它多提供了一层间接性,不过它也因此付出空间和执行效率两方面的代价就是了。

    需要多少内存才能够表现一个 class object?

    • 所有非静态数据成员的大小。
    • 由内存对齐而填补的内存大小。
    • 为了支持virtual有内部产生的额外负担。
      如下类:
    class ZooAnimal {  
        public:  
        ZooAnimal();  
        virtual ~ZooAnimal();  
        virtual void rotate();  
        protected:  
        int loc;  
        String name;  
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在32位计算机上所占内存为16字节:int四字节,String8字节(一个表示长度的整形,一个指向字符串的指针),以及一个指向虚函数表的指针vptr。对于继承类则为基类的内存大小加上本身数据成员的大小。

    指针类型

    “指针类型”会教导编译器如何解释某个特定地址中的内存内容及其大小:

    • 一个指向地址1000的整数指针,在32位机器上,将涵盖地址空间1000~1003(译注:因为32位机器上的整数是4-bytes)
    • 一个指向地址1000而类型为void的指针,将涵盖怎样的地址空间呢?是的,我们不知道!这就是为什么一个类型为void的指针只能够含有一个地址,而不能够通过它操作所指之object的缘故。

    所以,转型(cast)其实是一种编译器指令。大部分情况下它并不改变一个指针所含的真正地址,它只影响“被指出之内存的大小和其内容”的解释方式。

    加上多态后

    好,假设我们的 Bear object放在地址1000处,一个Bear指针和一个ZooAnimal 指针有什么不同?

    Bear b;
    ZooAnimal *pz = &b;    //Bear继承自ZooAnimal
    Bear *pb = &b;
    
    • 1
    • 2
    • 3

    它们每个都指向Bear object的第一个byte.其间的差别是,pb所涵盖的地址包含整个 Bear object,而pz所涵盖的地址只包含 Bear object中的 ZooAnimal subobject.
    自己编写的例子

    #include <iostream>;
    using namespace std;
    class base {
    public:
        virtual void o()
        {
            cout << "base" << endl;
        }
    };
    class A : public base {
    public:
        int a = 1;
        virtual void o()
        {
            cout << "a" << endl;
        }
    };
    class B : public base {
    public:
        virtual void o()
        {
            cout << "b" << endl;
        }
    };
    int main()
    {
        A se;
        base& b = se;
        b.o();
        cout << b.a;	//此处报错: 类 "base" 没有成员 "a"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    所以多态的应用重点在于虚函数上,因为只要有虚函数的类,就有虚指针。

    C++有三种方式支持多态

    1、经由一组隐式的转化操作,比如将派生类指针转化为指向其基类的指针 shape *ps =new circle();

    2、经由virtual function机制 ps->rotate()

    3、经由dynamic_cast 和typeid运算符

    if(circle _pc = dynamic_cast (ps))

  • 相关阅读:
    PV 操作与案例分析
    GoWeb 的 MVC 入门实战案例,基于 Iris 框架实现(附案例全代码)
    cell delay和net delay
    什么专业越老越吃香?
    微信小程序检查版本更新
    Mybatis-plus工具学习笔记(1)---[基本概述,入门案例搭建,通用service接口使用]
    python算法例14 整数加法
    MOCK远程API调用的简单实现
    什么是ChatGPT
    vue el-table字段点击出现el-input输入框,失焦保存
  • 原文地址:https://blog.csdn.net/q2453303961/article/details/125461396