zoukankan      html  css  js  c++  java
  • 《inside the c++ object model》读书笔记 之四 Function 语意学

    4.1 Member 的各种调用方式:

    1)nonstatic member function:

    ...C++的设计准则之一就是:nonstatic member function至少必须和一般的农member function 有相同的效率.
      实际上member function被内化为nonmember的形式.过程如下:
      a)改写函数的signature(函数的原型)以安插一个额外的参数到member function中,用以提供一个存取管道,使class object得以调用该函数,该额外的参数就是this指针.
      b)将每一个"对nonstatic data member"的存取操作改为经由this指针来存取.
      c)将member function重新写成一个外部函数,对函数名称进行"mangling"处理,使它在程序中成为一个独一无二的语汇.

    2)virtual mmeber function:

    ...调用virtual member function会被转化为,经由this,vptr,以及相应的索引值,来调用.
      使用class scope operator明确调用一个virtual fucntion,其决议方式会和nonstatic memberfunction一样,经由一个class object调用一个virtual function,这种操作应该总是被编译器对待一般的nonstatic member function一样地加以决议.

    3)static member function:

    ...static member function的主要特性是它没有this指针,一下是其次要特性:
      a)它不能直接存取其class中的nonstatic members.
      b)它不能够被声明为const,volatile或virtual.
      c)它不需要经由class object才被调用.

      如果取一个static member function的地址,获得将是其在内存中的位置,也即是其地址,由于static member function没有this指针,所以地址的类型并不是一个"指向class member function的指针",而是一个"nonmember函数指针".

    4.2 virtual member function

    ...为了支持virtual function机制,必须首先能够对于多态对象有某种形式的"执行期类型识别",有了RTTI就可以在执行期查询一个多态的pointer或是reference.这份额外的的执行期信息,只要class有一个virtual function,它就需要这份信息.

      在实现上,可以再每一个多态的class object身上增加两个members:
      1)一个字符串或数字,表示class类型.
      2)一个指针,指向某表格,表格中带有程序的virtual function的执行期地址.
      3)为了找到表格,每一个class object被安插一个有编译器内部产生的指针,指向该表格.
      4)为了找到函数地址,每一个virtual function被指派一个表格索引值.

      一个class只会有一个virtual table,每一个table内含其对应的class object中所有active virtual function函数实体的地址,这些active functions包括:
      1)这个class所定义的函数实体,它会改写(overriding)一个可能存在的base class virtual function函数实体.
      2)继承自base class的函数实体.
      3)一个pure_virtual_called()函数实体,它既可以扮演pure virtual function的空间保护角色,也可以当做执行期异常处理函数.

    ...多重继承下的virtual:
      在多重继承中支持virtual functions,其复杂度一般在第二个及后继base classes身上,以及"必须在执行期调整this指针"这一点.
      一般的处理方法是,经由指向"第二或后继之base class指针(或是reference)"来调用derived class virtual function,该调用所连带的"必要的this指针调整"操作,必须在执行期完成,一个比较有效地方法是利用thunk技术,所谓的thunk是一小段assembly码,用来(1)以适当的offset值调整this指针,(2)跳到virtual function去.
      thunk技术允许virtual table slot继续内含一个简单的指针,因此多重继承不需要任何空间上的额外负担.

      多重继承下,一个derived class内含n-1个额外的virtual tables,n表示其上一层base class的数目(单继承不会有额外的virtual table),针对每一个virtual function table,derived 对象中都有对应的vptr,vptrs将在constructor中被设立初值.
      因此,当讲一个derived class对象地址指定给一个base1(最左端base class)指针,被处理的将是主表格,当将一个derived class 对象地址指定给后继base指针时,被处理的将是次要表格.

      有三种情况第二或后继的base class会影响对virtual functions的支持:
      1)通过一个"指向第二个base class"的指针,调用derived class virtual function.
      2)通过一个"指向derived class"的指针,调用第二或后继个base 中一个继承而来的virtual function.
      3)第三种情况发生于一个语言扩充性质下,允许一个virtual function 的返回类型有所变化,可能是base type,也可能是publicly derived type.

      Microsoft以所谓的"adderss points"来取代所谓thunk策略,即,将用来改写别人的那个函数(也就是overriding function)期待获得的是"引入该virtual function之class"的地址,这就是该函数的"address point".

    ...虚拟继承下的virtual function:
      虚拟的单一继承并不像非虚拟的单一继承那样简单,derived 和base class 之间的转换需要调整this指针.
      另外,不要在virtual base class中声明nonstatic data members!

    4.3指向member function的指针:

    ...取一个nonstatic member function的地址,如果该函数是nonvirtual,则得到的结果是它在内存中的真正地址,然而这个值是不完全的,它也需要被绑定于某个class object的地址上,才能够通过它调用该函数,所有的nonstatic member function都需要对象的地址(以参数this指出).
      指向member function的指针声明语法,以及指向"member selection 运算符"的指针,其作用结果是作为this指针的空间保留者.
      使用一个"member function指针",如果并不用于 virtual function,多重继承,virtual base classes等情况的话,并不会比使用一个"nonmember function指针"的成本高.

    ...支持"指向virtual member function"的指针:
      对一个virtual member function取其地址,所能获得的只是一个索引值.
      对于一个"指向member fucntion的指针"评估求值,会因为该值有两种意义而复杂化,其调用操作也将会有别于常规的调用操作.

    ..在多重继承之下,指向member function的指针:
      为了让指向member function的指针也能够支持多重继承和虚拟继承,设计了如下的结构体:
      struct _mptr{
        int delta;
        int index;    //virtual table的索引值
        uion{
            ptrtofunc faddr;    //nonvirtual                 //member function 地址
            int v_offset;
        }
      }
    许多编译器在自身内部根据不同的classes特性提供多种指向member function的指针形式,如Microsoft提供了三种形式:
      1)一个单一继承实例(其中带有vcall thunk地址或是函数地址);
      2)一个多重继承实例(其中带有faddr和delta两个members);
      3)一个虚拟继承实例(其中带有四个members);


    4.4inline function:
    ...一般而言,处理一个inline函数,有两个阶段:
      1)分析函数定义,以决定函数的"intrinsin inline ability"(本质的inline能力).
      如果函数因其复杂度,或因其构建问题,被判断不可成为inline,它会被转化为一个static函数,并在"被编译模块"内产生对应的函数定义.
      2)真正的inline函数扩展操作是在调用的那一点上,这回带来参数的求值操作以及临时性对象的管理.

    ...形式参数:
      在inline函数扩展期间,每一个形式参数 都会被对应的实际参数取代,一般而言,面对"会带来副作用的实际参数",或是一个常量表达式,通常都需要引入临时性对象,如果既不是常量表达式,也不是个带有副作用的表达式,那么就直接代换之.

    ...局部变量:
      一般而言,inline函数中的每一个局部变量都必须被放在函数调用的一个封闭区段中,拥有一个独一无二的名称.如果inline函数以单一表达式扩展多次,那么每次扩展都需要自己的一组局部变量,如果inline函数以分离的多个式子被扩展多次,那么只需要一组局部变量,就可以重复使用(因为它们被放在一个封闭区段中,有自己的scope).

  • 相关阅读:
    与众不同 windows phone (39)
    与众不同 windows phone (38)
    与众不同 windows phone (37)
    与众不同 windows phone (36)
    与众不同 windows phone (35)
    与众不同 windows phone (34)
    重新想象 Windows 8 Store Apps 系列文章索引
    重新想象 Windows 8 Store Apps (71)
    重新想象 Windows 8 Store Apps (70)
    重新想象 Windows 8 Store Apps (69)
  • 原文地址:https://www.cnblogs.com/suiyu/p/2657620.html
Copyright © 2011-2022 走看看