《深度探索C++对象模型》读书笔记第四章:Function语意学


  1. C++中类的非静态成员函数和一般函数具有相同的效率,编译器内部会将成员函数转化为对等的普通函数实体,比如加上 this 指针。
  2. 一般而言,编译器对函数会用 ”mangling“ 手法进行命名处理,这也是函数重载的支持手段。
  3. 独立于 class object 之外的存取操作,在某个时候特别重要。比如说 static 成员函数,它的主要特性是没有 this 指针,因此差不多等同于非成员函数,所以它可以成为 callback 函数,可以成功地应用在线程(threads)函数上(见识过了)。
  4. 直接使用基类指针指向使用 new 分配的派生类对象,如: point ptr = new point3d;这种多态在编译期可以完成,virtual base class 的情况除外。这种多态称为消极多态。而当被指出的对象是编译器才能决定的,就成为积极多态了。如:ptr->z(),执行期传指针给 ptr,确定 ptr 的真正类型。
  5. 一个 class 中 vtbl 含有所有的活跃虚函数实体的地址,包括:(1)这个 class 锁定地的虚函数实体,它会 overriding 一个可能存在的基类虚函数实体。(2)继承自基类的函数实体,这是在派生类决定不 overriding 时才会出现的情况。(3)一个 pure_virtual_called() 函数实体,它既可以扮演 pure virtual function 的空间保卫者角色,也可以当作执行器异常处理函数(有时会用到)。(最后一点暂时不太懂)
  6. 在多重继承中支持虚函数,其复杂度围绕在第二个或后继基类身上,以及 ”必须调整 this 指针” 这一点。
  7. 多重继承中调整指针(注意没说虚函数):比如对于 base *pbase = new derived(没有多态),新的 derived 对象必须调整this 指针,以指向 base subobject。如果没有这样的调整,指针的任何非多态运用都将失败,像 base->data_base,存取操作都会失败!或者 delete base,这个操作执行时又必须把 this 指针指到头部,因为要析构的大小是 derived 对象大小。这些操作必须在执行期完成,也就是说 this 指针跳跃的这些 offset 必须知道,其实会存于 vtbl 之中。如果 base 是派生类的最基类,那么 this 指针无需调整,因为它们起始位置是一样的。
  8. 有三种情况,第二或后继的基类会影响对虚函数的支持:(1)通过一个指向第二基类的指针,调用派生类虚函数(指针必须后移)。(2)通过一个派生类的指针,调用第二个基类中一个继承而来的 virtual function。此情况下,派生类指针必须再次调整,以指向第二个基类子对象。(3)第三种情况发生于一个语言扩充性质之下,允许一个 虚函数返回值类型发生变化,可能是基类类型,也可能是共有派生类类型。比如 base *pb = pb->clone(),该函数返回值为 derived*类型,所以在此处必须调整 offset。


附录:
成员函数指针获取及测试是否支持多态,以及&point::x取成员函数地址偏移量操作(取出的不是地址)测试:
class point {
public:
    virtual float z() { return 0.0; };
};

class point3d : public point {
public:
    point3d(float z) : z_(z) { } 
    virtual float z() { return z_; };
private:
    float z_; 
};

int main()
{
    float (point::*pmf)() = &point::z;
    point *ptr = new point3d(5);
    float res = (ptr->*pmf)();  //测试是否同 ptr->z() 一样支持多态。
    std::cout<<res<<std::endl;  //输出 5,证明支持
 
    std::cout<<&point::z<<std::endl;  //输出函数地址偏移量:1

    return 0;
}
输出结果:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值