[读书笔记]深度探索C++模型_第四章_Function语意学

4.1 Member 的各种调用方式

Nonstatic Member Functions

编译器内部已将“member函数实例”转换为对等的“nonmember函数实例”
例如

float Point3d::magnitude() const
{
    return sqrt(_x*_x + _y*_y + _z*_z);
}

会被转换为

float magnitude3d(const Point3d * _this)
{
    return sqrt(_this->_x * _this->_x +
                _this->_y * _this->_y +
                _this->_z * _this->_z );
}

成员函数到非成员函数的转换过程

  1. 改写函数的 signature 安插一个 this 指针。
  2. 将每一个“对 nonstatic data member 的存取操作”改为经由 this 指针来存取。
  3. 将 member function 重新写成一个外部函数。将函数名称经过“mangling”处理,使它在程序中成为独一无二的词汇。

Static Member Functions

如果 Point3d::normalize() 是一个 static member function,以下两个调用操作:

obj.normalize();
ptr->normalize();

将被转换为一般的 nonmember 函数调用,像这样:

//obj.normalize();
normalize_7Point3dSFv();
//ptr->normalize();
normalize_7Point3dSFv();

由cfront 2.0 所引入的 static member functions。Staic member functions 的主要特征就是它没有 this 指针。以下的次要特征统统根源于其主要特征:

  • 它不能够直接存取其 class 中的 nonstatic members。
  • 它不能够被声明为 const、valatile 或 virtual。
  • 它不需要经由 class object 才被调用—-虽然大部分时候它是这样被调用的~

4.2 Virtual Member Functions

一个 class 只会有一个 virtual table。每一个 table 内含其对应之 class object 中所有 active virtual functions 函数实例的地址。这些 active virtual functions 包括:

  • 这一 class 所定义的函数实例。它会改写(overrideing)一个可能存在的 base class virtual function 函数实例。
  • 继承自 base class 的函数实例。这是在 derived class 决定不改写 virtual function 时才会出现的情况。
  • 一个pure_virtual_called()函数实例,它既可以扮演 pure virtual function 的空间保护者角色,也可以当做执行期异常处理函数(有时会用到)。
 class Point
{
public:
    virtual ~Point();

    virtual Point& mult( float ) = 0;
    //... 其他操作

    float x() const { return _x; }
    virtual float y() const { return 0; }
    virtual float z() const { return 0; }
    // ...

protected:
    Point( float x = 0.0 );
    float _x;
};

virtual destructor 被指派 slot 1,而 mult() 被指派 slot 2。此例并没有 mult() 的函数定义,所以 pure_virtual_called() 的函数地址会被放在 slot 2 中。如果该函数意外地被调用,通常的操作是结束掉这个程序。y()被指派 slot 3 而 z() 被指派 slot 4。x()的 slot 是多少?答案是没有,因为x()并非virtual function。
这里写图片描述
一般

ptr->z();

这样的式子会在编译期间

  • 经由ptr可以存取到该对象的 virtual table。
  • 每一个z()函数地址都被放在了 slot4 中。
    编译器将该调用转化为:
 ( *ptr->vptr[4] )( ptr );

在这一转化中,vptr 表示编译器所安插的指针,指向 virtual table;4表示 z()被指派的 slot 编号(关系到Point 体系的 virtual table)。唯一一个在执行期才能知道的东西是:slot 4 所指的到底是哪一个z()函数实例?

多重继承下的Virtual Functions

在多重继承之下,一个 derived class 内含 n-1 个额外的 virtual tables,n表示其上一层 base classes 的个数。对于本例的 Derived 而言,会有两个 virtual tables 被编译器产生出来:

  1. 一个主要实例,与 Base1(最左端 base class)共享。
  2. 一个次要实例,与Base2(第二个 base class)有关。
    针对每一个 virtual tables,Derived 对象中有对应的 vptr。通过指针调用各个方法,主要是通过调整this指针,上下移动来调用。

这里写图片描述

虚拟继承下的 Virtual Functions

不要在一个 virtual base class 中声明 nonstatic data members。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值