zoukankan      html  css  js  c++  java
  • c++ object model

    对一个结构体进行不断的封装后可以形成一个c++类,为此需要添加很多函数成员之类的代码,为此显示c++比c语言显得庞大并且迟缓,但是事实并不是这些

    c++在布局和时间上的额外承担主要是由virtual引起的

    下面简述c++对象模型

    数据成员包括静态成员和非静态成员,

    函数成员包括静态,非静态,虚函数

    --------------------------------------------

    c++对象模型

    (1)简单对象模型

    每一个对象存储着若干个slots,每一个slots指向一个成员,这里面包括函数成员和数据成员,对于顺序,索引则按照他们的声明顺序进行排序

    这样每一个成员都不存储在对象中,而是通过对象内的一个slots指针指向自己,这样可以解决因为数据成员的类型不同,而需要开辟不同的空间而导致的不必要的麻烦

    这种模式很少被应用到工业中,但是slots得思想和索引的概念影响着其他的模型

    (2)表格驱动对象模型(双表格模型)

    此种模型将所有的数据成员抽象出来,讲date member直接存储放在一个表中,而member function 的slots放在另外一个表中,我们对象本身只有两个指针,一个指针指向数据成员,一个指针指向函数成员表,表中有一系列的slots,在通过slots找到各个函数,这里的机制就类似于简单对象模型

    (3)c++对象模型:

    此模型主要在简单模型的基础上进行了一些列的优化,首先对于数据成员:非静态的直接存储在object内部,对于静态的则存储在class外,

    对于函数成员来说,静态成员函数和非静态成员函数也都存在类之外,对于虚函数(每一个object产生一个指针,指向virtual table,这个table内有一些列slots,分别指向各个虚函数)

    优缺点:这个模型在存取时间和空间上的效率得到了改善,但是如果非静态数据成员进行了更改,那么程序需要重新编译。和双表格模型比较,其空间效率和时间更好,但是双表格模型由于中间又一次间接引用,所以即使非静态数据成员进行了更改,也没有问题,其弹性比较好

    如果再次基础上,加上了继承的话,

    那么我们可以在每一个object中增加一个bptr指针,每一个指针指向一个base table,table里面有一些列的slots,每一个slots指向一个base function

    上面方法的缺点就是随着继承深度的增加,间接性的寻址,随着深度的增加时间也在增减,其时间和空间都消耗许多

    优点就是其对于每一个object的继承方式都表现为一致性,无需改变class本身,都可以改变base class table,class object只需要一个bptr指向其base table就ok了

    *****在c++对象模型的virtual table中的第一个索引是一个type_info for class 这这标记表示了我这个对象指向了哪一个类

    eg:

    A *P =NEW A()  

    A*P=new B()

    第一种就是指向A,第二种就是指向B

    但是对于c++对象模型来说,很多成员函数和静态成员都独立于对象存储,那么我们怎么找到他

    对于static date member

    它被编译器提出于class之外,并被视为一个global变量(但只在class生命范围之内可见)

    每个静态数据成员只有一个实体,存放在程序的数据段之中,

    经由’.’运算符,对一个静态数据成员进行存取操作,只是语法上的一种便宜行事而已。静态数据成员其实并不在class object之中,因此存取它并不需要通过class object。

    虽然你可以不靠class object 来存取一个静态成员,但其存取函数却得绑定于一个class object之上。(若静态成员的访问控制为protected或private,则必须通过存取函数来访问)

    成员函数的处理

    C++的设计准则之一:非静态成员函数至少和一般的外部函数有相同的存储效率。

    C++编译器会把成员函数内化为一般的函数:

    ①改写函数原型,安插一个额外的参数this指针。用以提供一个存取管道,使类对象得以调用该函数。

    int A::foo (A* const this)

    若该成员函数是const,则变成:

    int A::foo (const A* const this)

    ②对函数体中 类对象的非静态数据成员的存取操作,改为经由this指针来存取。

    int A::foo (A* const this)

    {            return  this->val ;             }

    ③将成员函数重新写成一个外部函数,对函数名称进行处理,使它在程序中成为独一无二的。

    A objA ;  
    A * ptr = & objA ;  
      
    ptr->foo( ) ;   
    objA.foo() ;  
    //分别被转换为:  
    foo_intA( ptr ) ;  
    foo_intA( & objA ) ;  

    静态成员函数的主要特征是它没有this指针,但是他仍然需要改一个新的函数名

    故其:

    ①它不能够直接存取其class中的非静态成员

    ②它不能够直接被声明为const、virtual

    ③它不需要经由class object才被调用——虽然大部分时候它是这样被调用的。

    1. objA.staFun( ) ;  
    2. ptr->staFun( ) ;  
    3. //会转换为:  
    4. staFun_staticintvoid( ) ;  
    5. staFun_staticintvoid( ) ;

     因为不需要this指针,所以他等同于外部函数,只不过他的内部操作成员都是类内的static data member

  • 相关阅读:
    centos已经安装了python2,同时安装python3
    linux下判断磁盘是ssd还是hdd
    Java中如何判断两个对象是否相等
    NPOI导出Excel和基于office导出Excel比较
    asp
    又找到了一个blog
    关于宋朝及中国历史的一点想法
    Android中实现EditText圆角
    Python小练习
    软件架构设计(三) 架构、架构师和架构设计
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/6284044.html
Copyright © 2011-2022 走看看