对象模型

对象
1、使用类进行封装的成本

相对于C语言来说,C++的类的封装对普通的数据成员和非内联函数并没有增加什么成本,

非内联函数虽然都是在类的内部声明,但是其实现却是在类外并且只有一个实体

内联函数只会在类的使用者(类对象)产生实际的实体

C++真正会增加成本的是对于虚函数和虚基类的实现上。

简单对象模型

    简单对象模型的概念就是对象的所有的数据成员和成员函数都不是直接的存储在对象的内部,为所有的对象的成员每个人都分配了一个插槽,存储自己的指针,

这样的话通过插槽的下标即可找到相应的对象的成员(数据成员或者是成员函数)。

\”\”

表格驱动对象模型

    简单对象模型的不足之处就是在实际的运作中没有办法提供统一的操作手段,因为不同的插槽可能是函数或者数据成员,

表格驱动对象模型就是解决这个问题:把所有的数据成员存储在一个表格中,所有的成员函数存储在一个表格中,在对象的内部只存储指向这两个表格的指针即可。

存储数据的表格直接存储数据,存储函数的表格存储指向函数的指针。

\”\”

C++的对象模型

C++的对象模型是对简单对象模型的升级:

在C++的对象模型中

1、把所有的非静态数据成员都直接的放在对象的内部

2、把静态数据成员和所有的静态和非静态成员函数都放在对象的外部

3、针对所有的虚函数,类会生成一堆指向这些函数的指针存放在一张表中,叫做vtbl

 每个对象内部生成一个vptr指向格子的vtbl,vptr的创建和修改都是由类构造和析构函数来执行。

\”\”

在虚拟继承场景下的对象模型的两种讨论

在虚拟继承下,每个派生类都只含有基类的一个实体,那么在在派生类中如何找到或者是定位他自己的基类

第一种:

   如果是简单对象模型中,只需要在对象的一个插槽中存储其基类的地址即可

第二种:

    就是virtual base class table 的概念,对每个对象来说,该表创建时每个插槽就保存有其基类的地址,然后在对象的内部添加一个指向该表的指针

关于C++的继承模型,后继有讨论

对象模型是如何影响程序的

我的理解,通过上面的几种不同的对象模型可以看出,不同的对象模型,会导致我们实例化一个对象以及在后继的开发过程中通过该对象对函数的调动,对数据成员的修改

都会有不同的操作过程,尽管可能从表面的操作上看没有什么不同。

关键词所带来的差异

1、struct关键词在C++中和class并没有什么本质上的差别,因为类的差别在于其内部的结构差别,而不是仅仅因为他叫不同的名字就是有本质的上的差别了。

2、在C++中使用C的struct往往是在需要对一个数据集合集体的当做数据单元作为函数的参数而言的时候使用的。

对象的差异

1、C++中的多态的实现必须通过基类类型的指针或者是引用才能实现这个OO变成典范

2、在面向对象的变成典范中,对于一个指针或者是引用,程序员是没有办法判断具体的行为的,只有到运行期此时才能判定

3、C++多态的实现方式有以下几种:

1、通过隐式的转化操作,比如使用基类的指针指向派生类的对象

2、通过虚函数的方式,在运行时期决议究竟使用的是哪个具体的派生类

3、通过dynamic_cast,把一个基类的对象指针强转化成派生类的对象

注意:

dynamic_cast (expression)
该运算符把expression转换成type-id类型的对象。Type-id 必须是类的指针、类的引用或者void*;
如果 type-id 是类指针类型,那么expression也必须是一个指针,如果 type-id 是一个引用,那么 expression 也必须是一个引用。
dynamic_cast运算符可以在执行期决定真正的类型。如果 downcast 是安全的(也就说,如果基类指针或者引用确实指向一个派生类对象)这个运算符会传回适当转型过的指针。如果 downcast 不安全,这个运算符会传回空指针(也就是说,基类指针或者引用没有指向一个派生类对象)。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
一个对象的大小主要由:
1、其中的非静态数据成员所占用的空间
2、由于需要内存对齐填补的空间
3、对虚函数支持需要的额外的空间(vptr)

指针的类型:
1、不同的类型的指针的区别不在于其表示方法不同,其不在于其指向的地址的不同(都是内存中的一段地址),不同点在于地址指向的内存区域被编译器解释成不同的类型。

2、对指针的类型的转换并不影响其指针所指向的地址大小,影响的是编译器对该地址起始的位置的数据的解释方式不同

多态对指针的影响:
1、使用基类的指针指向派生类的对象,和使用一个派生类类型的指针指向派生类对象是不同的,此时两个指针的范围不同
基类的指针的范围只是基类的范围,往往要比派生类小
2、如果使用派生类对象初始化基类对象,那么派生类对象会被切割同基类相同的大小。
3、之所以指针或者是引用能够实现多态就是因为,不同的类型不会导致他们在内存中的关于类型的不同的操作,只会对他们所占有的内存的大小和意义的不同的解释而已。

执行期语义学
1、程序在执行期间和我们实际写代码之间有着很大的差别,编译器当我们new一个对象的时候,使用赋值语句或者==运算符的时候,实际上进行了很多的隐式的操作。
一、对象的构造和解构
1、一个对象从他呗创建开始,代码区块中所有会返回的地方编译器都会放置析构函数。
2、一般我们尽量把一个对象定义在需要使用它的那段代码的附近,这样可以避免不必要的对象的产生和销毁的操作。这也是我们常说的对象哪里用就在哪里定义。

二、全局对象
1、全局对象存储在内存的静态存储区,一个全局对象在创建时要么被初始化要么其被分配到的内存的内容为0.
2、静态初始化,所谓的静态的初始化的操作指的是变量在编译期间就已经分配了内存,并且确定了值,惊天初始化的值放在静态存储区中,
如果一个类中的变量使用static 修饰一个变量,那么我们说该变量在编译阶段就已经确定了其占内存的大小,由于其属于类,所以不能够使用this 指针调用,因为this 指向的是具体的对象

三、局部静态变量
1、众所周知,局部静态对象有一个特点就是他每次使用会保存上一次被使用后的值,这是什么原理呢?
原因就是,由于是存储在静态存储区的,编译器保证他只会被构造一次,在第一次调用的时候,使用标识变量标识为true,当下一次调用的时候发现已经构造过,就不在构造了
当然析构函数也是一样。

四、对象数组

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值