4.2 Virtual Member Functions(虚拟成员函数)

如何输出类的非静态成员函数地址 源地址 http://blog.sina.com.cn/s/blog_6f6c0f350100w3zf.html 首先我们定义一个类Ctest,类里面包含三个不同形式的成员函数,静态成员函数statFunc()、动态成员函数dynFunc()虚拟函数virtFunc()。在main函数中我们利用cout标准输出流分别输出这三个函数的地址,程序如下所示: #include 阅读详情

一、两个基本概念

我们已经讨论过virtual function的一般实现模型:每个class 有一个virtual table,内含该class中有作用的virtual function的地址,然后每一个object有一个vptr,指向virtual table的所在。

在C++中,多态表示“以一个public base class的指针(或引用),寻址出一个derived class object“。如:

// Point2d : Point
Point* ptr_point = new Point2d();
Point &ref_point = new Point2d();

二、单一继承下的Virtual Functions

这里的单一继承指的是一般的单一继承,不是虚拟继承。在我们的Point class继承体系中:

// Point
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;
};

// Point2d : Point
class Point2d : public Point
{
public:
    Point2d(float x = 0.0, float y = 0.0)
        :Point(x), _y(y) {}

    ~Point2d();

    // 重写base class virtual functions
    Point2d& mult(float);
    float y() const { return _y; }
    // ... 其他操作

protected:
    float _y;
};

// Point3d : Point2d
class Point3d : public Point2d
{
public:
    Point3d(float x = 0.0, float y = 0.0, float z = 0.0)
        :Point2d(x, y), _z(z) {}

    ~Point3d();

    // 重写base class virtual functions
    Point3d& mult(float);
    float z() const { return _z; }
    // ... 其他操作

protected:
    float _z;
};

Point、Point2d和Point3d的内存布局和其virtual tables如下图所示:
内存布局和虚表

virtual destructor被指派slot 1,而mult()被指派slot 2,此例并没有mult()的函数定义(因为它是一个纯虚函数),所以pure_virtual_called()的函数地址会被放在slot 2中。如果该函数被意外的调用,通常的操作是结束掉这个程序。y()被只拍到slot 3,而z()被指派到slot 4。x()的slot是多少?并没有,因为它非virtual function。这里,内存布局只有数据成员和虚函数的虚表指针,并没有其他成员函数。如果该类中有static member,那么也不会出现在该内存布局中,因为static member存在于data segment,不在class object中。

关于成员函数位置的讨论

成员函数可以被看作是类作用域的全局函数,不在对象分配的空间里,只有虚函数才会在类对象里有一个指针,存放虚函数的地址等相关信息。成员函数的地址,编译期就已确定,并静态绑定或动态的绑定在对应的对象上。对象调用成员函数时,编译器可以确定这些函数的地址,并通过传入this指针和其他参数,完成函数的调用,所以类中就没有必要存储成员函数的信息。

这里写图片描述


三、虚拟继承下的Virtual Functions

考虑下面的virtual base class派生体系,从Point2d派生出Point3d:

class Point2d
{
public:
    Point2d(float x = 0.0, float y = 0.0);
    virtual ~Point2d();

    virtual void mumble();
    virtual float z();
    // ...

protected:
    float _x, _y;
};

// Point3d : public virtual Point2d
class Point3d : public virtual Point2d
{
public:
    Point3d(float x = 0.0, float y = 0.0, float z = 0.0);
    ~Point3d();

    float z();
protected:
    float _z;
};

虚继承下的内存布局如下图:

这里写图片描述

到这里我想上图已经看得有点神经错乱了,Lippman在P169页这样写道:

当一个 virtual base class从另一个 virtual base class 派生而来,并且两者都支持 virtual functions 和nonstatic data members 时,编译器对于 virtual base cIass 的 支持简直就像进了迷宫一样。虽然我手上有一整柜带有答案的例程,并且有一个以上的算法可以决定适当的 offsets以及各种调整,但这些素材实在太过诡异迷离,不适合在此处讨论!我的建议是,不要在一个 virtual base class中声明 nonstatic data members。 如果这么做,你会距离复杂的深渊愈来愈近,终不可拔。


四、多重继承下的Virtual Functions

虚拟成员函数Virtual Member Functions 首先,假设:       基类为Point *ptr;       ptr=new Point2d; Point2d为派生类。       z()为基类的虚拟成员函数,那么在调用ptr->z()时,这种使用基类指针来调用正确的z()实体的多态是怎么实现的?或者说,需要什么信息才能在执行期调用正确的z()? 要调用正确的z(),必须要知道两点:       1.ptr所指对象的真实类... 阅读详情

相关推荐

12Virtual Member Functions

为了支持virtual function机制,必须首先能够对于多态对象有某种形式的“执行期类型判断(runtime type resolution)”。也就是说以下的调用操作需要ptr在执行期的某些关键信息。ptr->z();如此一来,才能够找到并调用z()的适当实例。或许最直接了当但是成本最高的解决方法是把必要的信息加在ptr身上。在这样的策略下,一个指针(或是一个reference)持有两项信息。它所参考的对象的地址对象类型的某种结构,用以正确决议出z()函数实例的地址。

u012750235的博客 943

《深度探索C++对象模型》- 第4章 Function 语意学

这一遍看本书,总的说来收获并不大,也许是还没有遇到相关问题的缘故,另外也和最近的状态有关,有点浮躁。 看这一章有点看不下去的感觉了,没有什么新的收获,总结一下知识点吧。 1. Member Function共有3种:Nonstatic Member Function,Virtual Member Function,Static Member Function。 2. Static Member Function没有this指针,不能被声明为const、volatile或virtual。 3. obj

山高月小 800

C++对象模型——Virtual Member Functions (虚拟成员函数)(第四章)

4.2 Virtual Member Functions (虚拟成员函数) 已经看过了 virtual function的一般实现模型:每一个 class 有一个 virtual table,内含该 class 中有作用的 virtual function的地址,然后每个object有一个vptr,指向 virtual table的所在. 为了支持 virtual function机制,必须首

yiranant的专栏 1684

4章 Function 语意学2: Virtual Member Functions

每一个 class 有一个virtual table,内含该 class 之中有作用的 virtual function 的地址;然后每个 object有一个 vptr,指向 virtual table 的所在。

qq_40178082的博客 668

函数的效能 & 指向 Member Functions 的指针与其效能

nonmember friend 或 nonstatic member 或 static member 函数都会被转化为相同的形式, 因此三者的效率完全相同.另外, inline member function 的效率一直是最高的(前提是简单操作), 优化后的效率更是高, 这是因为编译器会将被视为不变的表达式提到循环之外, 因此只计算一次, inline 函数不只能够节省一般函数所调用的...

baochuanying9531的博客 157

Virtual Member Functions(虚拟成员函数)

实现模型:每一个class 只会有一个virtual table,内含该class之中有作用的virtual function的地址,每一个object有一个vptr(多继承可能有多个),指向virtual table的所在。 虚函数的地址以及存放虚函数地址的虚表在编译时期就确定下来了,不需要执行期的介入。执行期要做的是,激活虚函数 1.单一继承 单一继承的原理: ①继承基类的虚函数实体:基类所有虚函数实体的地址会被拷贝到derived class的virtual table相对应的slot之中。 ②重写

ZZHinclude的博客 471

13、指向Member Function的指针

或者和指向member function的指针声明语法,以及指向“member selection运算符”的指针,其作用是作为this指针的空间保留者。这也是为什么static member functions(没有this指针)的类型是“函数指针”,而不是“指向member function的指针”之故。

u012750235的博客 571

Virtual Member Functions & Static Member Function

如果一个 normalize() 是一个 virtual member function, 那么以下的调用: ptr->normalize(); 将会被内部转化为: (*ptr->vptr[1])(ptr); 其中:vptr 表示由编译器生成的指针, 指向 virtual table, 它被安插在每一个声明有(或继承自) virtual functinos 的 ...

weixin_34228617的博客 97

virtual member functions(单一继承情况)

virtual member functions(单一继承情况) virtual member functions的实现(就单一继承而言): 1.实现:首先会给有多态的class object身上增加两个members:一个字符串或数字便是class的类型,一个是指针,指向某表格,表格中带有程序的virtual functions的执行期的地址(具体一点是一个o...

HJ.Zhou 522

考虑可选的 virtual functions虚拟函数)的替代方法

 假设为视频游戏中角色设计了一个 hierarchy(继承体系)。游戏中有着变化多端的恶劣环境,角色被伤害或者其它的健康状态降低的情况并不罕见。因此决定提供一个 member function(成员函数)healthValue,它返回一个象征角色健康状况如何的整数。因为不同的角色计算健康值的方法可能不同,将 healthValue 声明为 virtual虚拟)似乎是显而易见的设计选择:c

armman的专栏 1095

Function 语意学

在前面文章《C++对象模型》可以知道,class 中成员函数的类型有:nonstatic member function、static member function、virtual member function;不同类型的成员函数的调用会有不同的表现,以下对每一种类型的成员函数进行简单的分析。

关注校招求职,微信号:job_campus 1255

Virtual Member Functions 的语意

看过之前的 virtual function可以知道其实现模型: 每一个 class 有一个 virtual table. 内含该 class 之中 有作用的 virtual function 地址, 然后每个 object 有一个 vptr, 指向 virtual table 的所在. 在这一节中, 需要走访一组可能的设计, 然后根据单一继承, 多重继承和虚拟继承的多种情况, 从细节上来探究这个...

weixin_34336292的博客 87

Inheritance and virtual functions

What is inheritance? models the ‘is-a’ relationship Why do it? Get all member functions and data of the base classes, for free, without having to (re-)write them yourself Using inherit

BitterCoffee 530

35. Consider alternatives to virtual functions

考虑virtual函数以外的其他选择 请记住: virtual函数的替代方案包括NV1手段及Stratery设计模式的多种形式。NVI手法自身是一个特殊形式的Template Method设计模式。 将机能从成员函数移到class外部函数,带来一个缺点是,非成员函数无法访问class的non-public成员。 tr1::funciton对象的行为就像一般函数指针。这样的对象可接纳"与给定...

xupeng1644的博客 1419

天外客AI翻译机SR-IOV virtual functions直通

本文深入解析天外客AI翻译机采用的SR-IOV Virtual Function直通技术,揭示其如何通过硬件级I/O优化实现低延迟网络传输。该技术将物理网卡虚拟出多个独立VF,直接分配给虚拟机,绕过传统虚拟化瓶颈,显著提升AI翻译场景下的实时性与性能。

weixin_36197669的博客 778

[20] Inheritance — virtual functions

FAQs in section [20]: [20.1] What is a "virtual member function"? [20.2] How can C++ achieve dynamic binding yet also static typing? [20.3] Whats the difference between how virtual a

1077
上一篇: 4.1 Member Function的各种调用方式
下一篇: 2.3 程序转化语意学
BigoSprite
博客等级 码龄11年 59粉丝 139原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值