抛砖引玉篇--member function

/ --*-- 2018.7.27 --*-- /

摘要:论述了C++对象模型中的member function,

           包括member function的类型及其在对象模型中所充当的角色,还有各function的执行效率

 

%note:c语言是面向过程的语言,代码重点在于如何高效的完成某个步骤。

              c++是面向对象的语言,除了效率,也注重代码本身的架构,

             力求在代码效率和重用性可扩展性之间寻求一个平衡点。

 

% c++支持三种类型的member function:

    static、nonstatic function, virtual function。

 

% nonstatic member-function:对nonstatic data member进行函数封装,执行操作方法

 nonstatic member-function的执行效率并不比nonmember function的差,

 nonstatic member-function最终也被编译器处理成弄nonmember function,

  过程如下:

  @1. 修改其signature,以插入一个额外参数:this指针

  @2. nonstatic-member function对nonstatic data member的操作由this指针直接完成,

         这一点比nonmember function的传参高效。

  @3.对函数进行 name-mangling, 确保函数名称是独一无二的。

 

% name-mangling技术提供了一种确保data member和member function名称独一无二的方法,使用到的地方有:

 @1.函数重载时,函数名称加上参数列表;

 @2.基类和派生类中有相同member时,变量名加上类名;

name-mangling技术是c++实现作用域的一种方法?

 

% virtual member-function

   是实现C++“多态”特性的关键所在:如何由class base指针调用derived class object的virtual member-function。

抛砖引玉篇--member function

其中:

ptr是this指针, vptr是指向虚函数表的指针。   

虚函数表存放的是虚函数的函数指针,通过索引1得到该指针,并传进this指针。

虚函数也会被name-mangling。(考虑·一个抽象基类有多个derived class时)

note:virtual member-function通过vptr指针间接引用,所以在效率上是比较低下的,

          但它确是c++多态的基本实现技术。

 

 

%static member-function

note: static member-function为操作static data-member提供了方法,

           但其没有传进this指针,所以:

            ##1.static function不能nonstatic data member;

           ##2.static function 不可能同时为const function;

 

 

抛砖引玉篇--member function

抛砖引玉篇--member function

可见,static-member function并没有传进this指针。

抛砖引玉篇--member function

 

抛砖引玉篇--member function

 

 

virtual member-function

virtual function的一般实现模型:

  每个含有虚函数的类拥有一张virtual table,用于存储virtual function的函数指针,

  每个基类的对象都有一个vptr,指向virtual table。

 

抛砖引玉篇--member function

  

note:polymorphism  -- 通过base class指针可以调用derived class objectvirtual function

 

抛砖引玉篇--member function

抛砖引玉篇--member function

抛砖引玉篇--member function

 

当发生继承时:

抛砖引玉篇--member function

 

 

当有以下调用发生时(ptr是一个基类指针):

抛砖引玉篇--member function

在编译期,编译器的工作是:

@1.通过ptr找到对象的vptr,

@2.通过vptr找到virtual table,并找到z()在virtual table中位置

      在执行期,根据编译期找到的z()所在的位置,执行实际的函数。

 

在单一继承情况下,virtual function模型即容易实现,而且有效率。

但在多重继承的情况下的支持就不是很完美了。

note单一继承时: base class object和derived class object所在内存地址空间的首地址是相同的, 

          所以base class指针可以直接找到vptr,

         但多重继承时,base class object和derived class object所在内存空间的首地址可能存在一定的offset,所以需要先对指针进          行调整。

 

 

抛砖引玉篇--member function

抛砖引玉篇--member function

抛砖引玉篇--member function

 

 

% 函数执行效率

  inline function:避免了函数调用,同时也增加了编译器优化的机会。

  nonmember function、nonstatic-member function、static-member function

  这三者的效率相当。

  virtual member function:多了一层间接引用,效率最低。

 

 

% friend function:

 :c++的封装特性,要求data member对外屏蔽,只能通过公共的member function进行操作。

   但有时候member function满足不了需求,例如:

   对nonstatic member-function总是得通过对象调用。

   对static member-function又无法操作nonstatic data-member。

   ##所以,需要提供另外一种特殊的方法可以访问到data-member。

 

 

% inline函数:为效率而存在(空间换时间),是C语言宏函数的进化。

抛砖引玉篇--member function

note:可见定义的inline函数,并不一定会被实现,编译器会进行判断是否实现为inline。

 

%在inline扩展期间,每一个型参都将被相应的实参所替代。

  可分三种情况讨论:

  @1.对于“会带来副作用的实参”,先引入临时变量,对实参进行求值操作, 再完成替换。

        避免了在执行期间,对实参进行重复求值的操作。

 

  @2.对于常量表达式,将常量代入,直接执行inline函数体内的操作,并得到结果。

 

  @3.除了上面两种情况以外的普通形参,直接替换。

 

 

example:

##1.

抛砖引玉篇--member function

##2.

抛砖引玉篇--member function

##3.

抛砖引玉篇--member function

 

 

% inline中的局部变量

  ##1.

抛砖引玉篇--member function

  ##2.

抛砖引玉篇--member function

抛砖引玉篇--member function

  ##3.

抛砖引玉篇--member function

抛砖引玉篇--member function

抛砖引玉篇--member function

 

抛砖引玉篇--member function

 

抛砖引玉篇--member function

 

抛砖引玉篇--member function

 

note:定义在类申明体中成员函数都是inline函数。

参考书籍:《Inside The C++ Object Model》