现在的位置: 首页 > 综合 > 正文

《深度探索C++对象模型》读书笔记之Function语意学

2013年09月15日 ⁄ 综合 ⁄ 共 1930字 ⁄ 字号 评论关闭

C++支持三种类型的成员函数:staticnonstaticvirtual

 

1C++的设计准则中说:非静态成员函数至少必须和一般的非成员函数有相同的效率。这是如何做到的?

C++中的member function实际上被转化为nonmember的形式。下面是转化的步骤:

1>    改写函数的原型,安插一个额外的参数(this指针)到member
function
中,使得class object得以调用该函数。

Point3d Point3d::magnitude()

Point3d Point3d::magnitude() const

      
分别被转化为

Point3d Point3d::magnitude(Point*const this)

Point3d Point3d::magnitude(const Point*const this)

2>    将每个“队nonstatic
data member
的存取操作”改为经由this指针来存取

3>    member
function
重写成一个外部函数,对名称进行“mangling”处理,使它在程序中成为独一无二的词汇。(name
mangling
的方法请Google之)

备注:静态函数的转化不难想象。而实际正如想象的那样。

 

2static memberfunction有何不同?

        
静态成员函数的主要特性是它没有this指针,以下次要特性统统根源于其主要特性:

1>    不能够直接存取其class中的nonstatic
members

2>    不能够被声明为constvolatilevirtual(前两者是为了限制nonstatic
member
,既然不能存取nonstatic members当然也不能使用这两者咯,后者虚机制,你懂的~

3>    不需要经由class
object
才被调用

 

3virutal memberfunction如何被调用?你会如果利用这些特性去优化你的程序?

1>    指针或者引用调用,会转变成通过虚函数指针调用虚函数表中的该函数(有一个决议的过程,低效啊!!!)

//register float mag = magnitude();

register float mag = (*this ->vptr[2])(this);

2>    如果能确定调用函数使用实体调用虚函数可以压抑由于虚机制而产生的不必要的重复操作。

//明确的调用会压抑虚机制

register float mag =Point3d::magnitude();

上述等同于调用一个nonstatic member function

 

4、虚函数的决议的支持机制是怎样的?

  
1
、单一继承:  

     编译期:

1>    为每个有虚函数的类配一张虚函数表,它存储该类类型信息和所有虚函数执行期的地址。

2>    为每个有虚函数的类插入一个指针(vptr,这个指针指向该类的虚函数表。

3>    给每一个虚函数指派一个在表中的索引。

执行期:在特定的virtual tableslot中激活virtual
function
。虽然我们并不知道ptr所指对象的真正类型,然而,经由ptr可以存取到该对象的virtual
table
。虽然我们不知道哪个f()将被调用,但我们知道每一个f()函数的地址都被放在第nslot

备注:构建virtualtable有三种情况:一、继承自base
class
的函数实体,其实体地址拷贝到对应的slot;二、类定义的函数体使用自己的函数实体地址放在对应的slot;三、类新加入的函数,增加virtual
table
尺寸,将新函数实体地址放入该slot。(纯虚函数可以起到占位作用,也要添加到virtual
table
中)

2、多重继承:

在多重继承中支持virtualfunction,其复杂度围绕在第二个及后继的base
classes
身上,必须在执行期调整this指针。解决的方式大致有一、Bjame的解决方法;二、thunk的方法。(在此不作多说,详细可参阅书籍)

3、虚继承:

        
略(因为太过复杂,书籍上并未详细讲解)。

 

5inline函数背后做了什么?

形式参数:每个形式参数都会被对应的实际参数取代;如果实际参数是个常量表达式则以临时变量代换之,避免重复求值。

局部变量:如果inline函数以单一的表达式扩展多次,那么每次扩展都需要自己的一组局部变量。如果inline函数以分离的多个式子被扩展多次,那么只需要一组局部变量。

  
备注:由于参数的副作用(使用太多启代换作用的临时变量),以单一表达式做多重调用,或是在inline函数中有多个局部变量,都会产生临时性对象。产生的大量的扩展码,使程序的大小暴涨。

抱歉!评论已关闭.