C++对象模型---第 4 章 Function语意学

1.Member Funcition的各种调用方式

  •  Nonstatic member funcion:

        编译器将其转为nonmember  Function的形式,转化步骤是:

            (1)添加额外的参数 ---- this指针

            (2)对每一个nonstatic data member的存取由this指针操作。(this指针提供了一个存取管道)

            (3)对函数名进行 mangling处理,使它在程序中成为独一无二的名词。

  • Virtual member function:

         编译器将其转为nonstatic member function,随后转化为nonmember function,具体如下:

             对于虚函数f(),obj.f()在编译器内部转化为:

                                               (* obj.vptr[1])(&obj)

             其中,1表示virtual table的索引值,即指向第1个slot。关联到normalize()函数。

  • Static member function:

        编译器会将其视为nonmember function的形式。        

        static member function 会提出于class声明之外,并经过mangling后有独立的名称。

        如果取一个static member function 的地址,获得的是其在内存中的真实物理地址,而不是一个指向“class member function”的指针,如下:

                     &Point::count();

                    会得到一个数值,类型是:

                        unsigned int(*)();               //普通的函数指针,表示真实的物理地址

                    而不是:

                        unsigned int(Point::*)();     //类成员函数指针,表示由this调控

2. Virtual Member Funcitons

  • C++中,多态表示以基类指针,寻址出一个派生类对象。每个类的virtual table中的active virtual function 包括:

            (1)override base class的函数实体。

            (2)继承自base class 的函数实体。

            (3)一个pure_virtual_called()。

  • 一个类继承函数virtual table的三种可能性:

            (1)继承base class 所声明的virtual functions的函数实体。(该函数实体的地址会被拷贝到derived class的virtual table相对应的slot之中)

            (2)使用自己的函数实体(改写了base class的virtual funciton)。(改写后的函数实体地址必须放在对应的slot之中)

            (3)可以加入一个新的virtual function。(这时候virtual table 的尺寸会增大一个slot放进这个函数实体地址)

  • 编译时期设定virtual function的调用:

                  调用z()时,虽然不知道其所指对象的真正类型,但是知道z()函数地址存放在virtual table的第4个slot中,编译器作出的转化为:

                        ptr->z()   ------>(*ptr->vptr[4])(ptr)

                  唯一一个在执行期才能知道的东西是:slot4所指的到底是哪一个z()函数实体,即ptr指向哪个虚表。

  • 多重继承下的 Virtual Functions

           (1) 在多重继承中支持virtual functions,“必须在执行期调整this 指针”。一般规则是:

                    经由指向“第二或后继base class的指针”来调用derived class virtual function。其中this指针的调整操作必须在执行期完成。

           (2) 多重继承下,一个drived class内含n-1个额外的virtual tables。(n表示继承的基类数量)   

           (3) 多重继承下的virtual table布局图:     

          

3. 指向 Member Funciton 的指针
  • 普通函数指针和类成员函数指针:
            普通函数指针:double (*p)(int,int)
            类成员函数指针:double(Class::*p)(int,int)
  • member 地址表示:
            (1)&nonstatic data member    ---->  Class::addr(类布局中的bytes位置)
            (2)&nonstatic member  function---->  addr(真实地址)
            (3)&nonstatic virtual member  function  ---->  函数在virtual table中的索引值
 
 
4. inline函数
  • inline函数请求的不同结果:
                编译器通过请求:将函数转变为表达式(常量)
                编译器拒绝请求:将函数转变为static函数
 
  • inline函数有局部变量的危险:
              局部变量会产生临时性对象,编译器可能没有移除他们。如果inline函数被调用多次的话,会产生很多临时对象,使程序体积暴涨。
原文地址:https://www.cnblogs.com/ladawn/p/8227931.html