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

本文详细解析了C++中成员函数的各种调用方式,包括非静态成员函数如何被转换为等效的非成员函数,静态成员函数的特点及其调用方式,以及虚函数的工作原理和在多重继承与虚继承中的表现。

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。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值