c++对象模型研究1:关于对象

对象模型

和c不同,c是将数据和处理数据的函数分开的(数据流过程决定函数编写,过程式的);而c++把数据和处理数据的方法关联在了一起(对象发起动作,操纵数据)。那么像class一样将数据和方法包含在一起,甚至再用上模板是否会增加布局成本呢?


C++对象模式

在C++中,有两种类成员数据:static和非static,以及三种类成员函数:static、非static和virtual。

在C++对象模型中,非static成员数据被配置于每一个类对象之内,static成员数据则被放在所有类对象之外。static和非static成员函数也被放在所有的类对象之外。


C++在布局以及存取时间上主要的额外负担是由virtual引起,包括

1.虚函数机制(执行时绑定)

2.虚基类。还有一些多重继承下的额外负担。


virtual函数则以两个步骤支持之:

1.每一个类产生出一堆指向virtual函数的指针,放在表格之中。这个表格被称为virtual表。

2.第一个类对象被添加了一个指针,指向相关的virtual表。这个指针的设定和重置都由每一个类的构造函数,析构函数和拷贝赋值运算符自动完成。另外,虚函数表地址的前面设置了一个指向type_info的指针,RTTI(Run Time Type Identification)运行时类型识别是有编译器在编译器生成的特殊类型信息,包括对象继承关系,对象本身的描述,RTTI是为多态而生成的信息,所以只有具有虚函数的对象在会生成。


和c相比,c++的布局成本主要来自于virtual,virtual使得class object需要先找虚表,再由虚表找所在地,增加了耗费。而像nonstatic data menber,跟c中struct完全一样,所以这些并不会增加c++的布局成本(相对于c而言)。


对于C++中的单继承

C++实际模型是:对于一般继承是扩充已有存在的虚函数表;对于虚继承添加一个虚函数表指针。


对于C++中的多继承

1)每一个基类都有自己的虚函数表,基类各有虚表

2)子类的虚函数被放到第一个基类的虚函数表中,子类与第一个父类共用一张虚表

3)内存布局中,基类的排列顺序就是基类的声明顺序

4)重写:每一个基类的虚表中的fun都被重写成子类的fun,这样做就是为了解决不同的基类类型的指针指向同一个子类实例,而能够调用到实际的函数。


对于C++中的多继承中的虚继承

虚继承的子类,有单独的虚函数表,另外也单独保存一份父类的虚函数表。


如何访问成员?

数据成员如何访问(直接取址)?

跟实际对象模型相关联,根据对象起始地址+偏移量取得。


函数成员如何访问(间接取址)?

跟实际对象模型相关联,普通函数(nonstatic、static)根据编译、链接的结果直接获取函数地址;如果是虚函数根据对象模型,取出对于虚函数地址,然后在虚函数表中查找函数地址。


多态如何实现?

多态(Polymorphisn)在C++中是通过虚函数实现的。如果类中有虚函数,编译器就会自动生成一个虚函数表,对象中包含一个指向虚函数表的指针。能够实现多态的关键在于:虚函数是允许被派生类重写的,在虚函数表中,派生类函数对覆盖(override)基类函数。除此之外,还必须通过指针或引用调用方法才行,将派生类对象赋给基类对象。


为什么析构函数设为虚函数是必要的?

这个写在《改善程序与设计的具体做法(C++)》中的条款7中。


ps:

本质上一个引用通常是以一个指针来实现,而且是const指针。



参考:

《深度探索C++对象模型》

http://www.cnblogs.com/skynet/p/3343726.html

http://blog.csdn.net/chinajane163/article/details/49798017

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当涉及到C++对象模型时,以下是一些额外的建议: 1. 理解对象的内存布局:了解对象的内存布局对于理解C++对象模型至关重要。对象的内存布局包括成员变量、虚函数表指针(vptr)和其他可能的额外信息。了解不同类型对象的内存布局可以帮助你更好地理解对象模型。 2. 学习虚函数和多态性:C++中的虚函数和多态性是实现运行时多态的重要概念。通过将函数声明为虚函数,并使用继承和多态性的特性,可以实现基类指针或引用调用派生类对象的方法。深入理解虚函数和多态性的原理和使用方法,可以更好地设计和组织你的代码。 3. 掌握虚函数表(vtable)的工作原理:虚函数表是实现动态绑定的关键机制之一。它是一个指针数组,其中每个指针指向对应的虚函数。当调用虚函数时,通过对象的虚函数表进行动态查找。了解虚函数表的工作原理和实现细节有助于深入理解对象模型。 4. 注意虚函数表指针(vptr)的使用:每个包含虚函数的类都有一个隐藏的虚函数表指针(vptr),它指向该类的虚函数表。在派生类中,vptr指针通常指向派生类的虚函数表,但在某些情况下,可能需要手动修改vptr指针以实现特定的行为。了解vptr的使用和潜在问题是很重要的。 5. 理解对象的构造和析构过程:对象的构造和析构过程是C++对象模型中的重要概念。构造函数用于初始化对象的成员变量,析构函数用于释放对象占用的资源。了解构造和析构过程的执行顺序、调用方式和注意事项,可以帮助你编写更安全和高效的代码。 6. 研究编译器的优化策略:不同的编译器可能会对C++对象模型进行不同的优化。了解编译器的优化策略,特别是与对象模型相关的优化,可以帮助你编写更高效的代码,并避免一些潜在的问题。 通过深入学习和实践,你将能够更好地理解和应用C++对象模型。记住,实践是掌握任何概念的关键,因此尽量编写和调试一些涉及对象模型的代码,以加深你对该主题的理解和熟练度。祝你在学习和应用C++对象模型时取得成功!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值