zoukankan      html  css  js  c++  java
  • 《深度探索C++对象模型》第四章 Function语意学

    member function相对于nonmember function之间不存在效率之间的差别,因为编译器内部已经将“member 函数实体”转化为对等的“nonmember 函数实体”,转化过程:
    1.改写函数的函数原型,以安插一个额外的参数到member function中,用于提供一个存储管道,使class object得以调用该函数,该额外参数被称为this指针。
    2.将每一个“对nonstatic data member的存取操作”改为经由this指针来存取
    3.将成员函数重新写成一个外部函数,对函数名称进行“mangling”处理,使它在程序中成为独一无二的词汇。

    名字的特殊处理(name mangling)
    一般而言,member的名字前会被加上class 的名称,形成独一无二的命名,例如:

    Class Bar{public: int val;}
    class Foo:public Bar{public int val;}
    //Foo 的内部
    class Foo
    {
    public :
    int ival_3bar;
    int ival_3foo;
    }

    不管要处理哪一个ival,都可以通过“name mangling”,都可以绝对清楚地指出来,由于member functions可以被重载化(overloaded),所以需要更广泛的mangling手法,以提供绝对独一无二的名称。


    Virtual Member Funtion(虚成员函数)
    如果normalize()是一个virtual member function,那么

    ptr->normalize();
    //将会被内部转化为下面这样
    (*ptr->vptr[1])(ptr);

    1.vptr表示由编译器产生的指针,指向virtual table,它被安插在每一个“声明有或继承自一个或多个virtual functions”的class object中,事实上其名称也会“mangled”,因为在一个复杂的class派生体系中,可能会存在多个vptrs。
    2.1是virtual table slot的索引值,关联到normailize()函数
    3.第二个ptr表示this指针。

    为了支持virtual function机制,必须首先能够对多态对象有某种形式的“执行器类型判断法”,在C++中,多态表示“以一个public base class 指针(或reference)寻址出一个derived class object”的意思。
    多态又可分为passive(消极)active(积极)

    Point*ptr=new Point2d;
    ptr=new Point3d;//这是消极的

    ptr的多态机能主要扮演一个传送机制的角色,经由它,我们可以在程序的任何地方采用一组public derived类型,这种多态形式被称为是passive的,可以在编译期完成(virtual base class除外
    当被指出的对象真正被使用时,多态也就变成了active的了,下面对于virtual function的调用

    ptr->z();//active的多态

    其中z()是一个virtual function,那么什么信息才能让我们在执行期调用正确的z()实体?我们要知道:
    1.ptr所指对象的真实类型,这可使我们选择正确的z()实体。
    2.z()实体位置,以便我们能够调用它。
    在实现上,可以在每一个多态的class object身上添加两个members
    1.一个字符串或者数字,表示class 的类型。
    2.一个指针,指向某表格,表格中带有程序的virtual functions的执行期地址。
    表格中的virutual functions地址如何被构建的?
    在编译时期(由上面的ptr=new Point3d可知)就可以获得virtual function的地址,此外,这一组地址是固定不变的,执行期不可能新增或替换之,由于程序执行时,表格的大小和内容都不会发生改变,所以其构建和存取都可以由编译器完全掌握,不需要执行器的任何接入。


    上面是准备好地址,接下来是如何寻址:
    1.为了找到表格,每一个class object被安插上一个由编译器内部产生的指针,指向该表格。
    2.为了找到函数地址,每一个virutual function被指派一个表格索引值。
    执行期要做的,只是在特定的记录着virutual function的地址激活virutal function


    一个class只会有一个virtual table,每一个table内涵其对应的class object中所有的active virtual functions函数实体的地址,这些active virtual function包括:
    1.这个class 所定义的函数实体,它会改写(overriging)一个可能存在的base class virtual function函数实体。
    2.继承自base class的函数实体,这是在derived class决定不该写virtual function时才会出现的情况。
    3.一个pure_virtual_called()函数的实体。
    每一个virtual function都派有一个固定的索引值,这个索引值在整个继承体系中与特定的virtual function相关联。
    这里写图片描述
    当B继承自A的时候:
    1.它可以继承base class所声明的virutal functions的函数实体,正确的说,是该函数实体的地址会被拷贝到派生类的virtual table相对应的slot中
    2.它可以使用自己的函数实体,这表示它自己的函数实体地址必须放在对应的slot中。
    3.它还可以加入一个新的virtual function。这时候virtual table的尺寸会增大一个slot,而新的函数实体地址也会放进该slot中。
    如果我有这样一个函数调用:

    ptr->z();

    那么我怎么拥有足够多的只是在编译时期设定virtual function调用呢?
    1.一般而言,我们不知道ptr所指对象的真正类型,但是我们可以知道,经由ptr可以存取到该对象的virtual table;
    2.虽然我们不知道哪一个z()会被调用,但我知道每一个z()函数的地址都被放在slot4中,这样我们就可以转化为:

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

    以上只包含单继承


    多继承下的虚函数
    图太难话我就直接截书里的图了
    (图太难画了,我直接截书里的图吧)
    在多重继承下,一个派生类内涵n个virtual table,n是上一层base classes的数目,针对每一个virtual tables,derived对象中有对应的vptr。

    https://github.com/li-zheng-hao
  • 相关阅读:
    flash bulider 无法启动
    -all_load,-ObjC,-force_load三者的区别
    使用NSOperation使用,创建线程中传递多个参数
    WebService开发步骤
    java的注释
    Struts2的创建Web项目入门
    Linux学习笔记
    CSS布局注意(纯属个人总结)
    java数据库连接类,已经把数据库操作的方法都封装好了
    CSS学习笔记总结和技巧
  • 原文地址:https://www.cnblogs.com/lizhenghao126/p/11053762.html
Copyright © 2011-2022 走看看