虚函数的机制

虚函数在类中的体现

对象的多态性需要通过虚表和虚表指针来完成,虚表指针被定义在对象首地址的前4字节处,因此虚函数必须作为成员函数使用。
由于非成员函数没有 this 指针,因此无法获得虚表指针,进而无法获取虚表,也就无法访问虚函数。

子类对虚函数进行了重写,所以如果是子类的指针,是访问不到父类的成员函数的。而父类的指针可以访问到子类的成员函数。

值得注意的是,虽然虚表是共享的,但是虚表指针并不是,类的每一个对象有一个属于它自己的虚表指针。

编译环境:VS2012

  • 类中只有普通成员函数:
class CClassA
{
public:
    void fun_a(){}
};

类大小图1

  • 类中含有虚函数:
class CClassA
{
public:
    virtual void fun_a(){}
};

类大小图2

由此可见,有虚函数的多了4个字节,这4个字节就是分给虚函数指针的.


虚函数表的存储机制

一般继承(无虚函数覆盖)

C++代码:

#include <iostream>
using namespace std;
class CClassA
{
public:
    virtual void fun_a(){}
    virtual void fun_b(){}
    virtual void fun_c(){}
};
class CClassB : public CClassA
{
public:
    virtual void fun_e(){}
    virtual void fun_f(){}
    virtual void fun_g(){}
};
int main()
{
    CClassA objA;
    CClassB objB;
    return 0;
}

反汇编代码:

  • CClassB 的虚函数表
CONST   SEGMENT
??_7CClassB@@6B@ DD FLAT:??_R4CClassB@@6B@      ; CClassB::`vftable'
    DD  FLAT:?fun_a@CClassA@@UAEXXZ
    DD  FLAT:?fun_b@CClassA@@UAEXXZ
    DD  FLAT:?fun_c@CClassA@@UAEXXZ
    DD  FLAT:?fun_e@CClassB@@UAEXXZ
    DD  FLAT:?fun_f@CClassB@@UAEXXZ
    DD  FLAT:?fun_g@CClassB@@UAEXXZ
CONST   ENDS
  • CClassA 的虚函数表
CONST   SEGMENT
??_7CClassA@@6B@ DD FLAT:??_R4CClassA@@6B@      ; CClassA::`vftable'
    DD  FLAT:?fun_a@CClassA@@UAEXXZ
    DD  FLAT:?fun_b@CClassA@@UAEXXZ
    DD  FLAT:?fun_c@CClassA@@UAEXXZ
CONST   ENDS

可以看到,虚函数表存放在常量段里(模块的数据段通常存放该模块的全局数据和静态数据,这样我们可以把虚表看作是模块的全局数据或者静态数据),并且 CClassB 继承 CClassA 后,虚函数表中的函数排列顺序为先基类再子类。

也可以在内存中证明排列顺序,如图:
objB 的前三个是 objA 的三个函数

objB-objA

可得objB 的虚函数结构为:
objB 的虚函数结构


一般继承(有虚函数覆盖)

C++代码:

class CClassA
{
public:
    virtual void fun_a(){}
    virtual void fun_b(){}
    virtual void fun_c(){}
};
class CClassB : public CClassA
{
public:
    virtual void fun_a(){}   //覆盖基类的fun_a
    virtual void fun_f(){}
    virtual void fun_g(){}
};

汇编中的虚函数表:

  • CClassB: (这里 fun_a 已经不再是 CClassA 的了)
CONST   SEGMENT
??_7CClassB@@6B@ DD FLAT:??_R4CClassB@@6B@      ; CClassB::`vftable'
    DD  FLAT:?fun_a@CClassB@@UAEXXZ
    DD  FLAT:?fun_b@CClassA@@UAEXXZ
    DD  FLAT:?fun_c@CClassA@@UAEXXZ
    DD  FLAT:?fun_f@CClassB@@UAEXXZ
    DD  FLAT:?fun_g@CClassB@@UAEXXZ
CONST   ENDS
  • CClassA:
CONST   SEGMENT
??_7CClassA@@6B@ DD FLAT:??_R4CClassA@@6B@      ; CClassA::`vftable'
    DD  FLAT:?fun_a@CClassA@@UAEXXZ
    DD  FLAT:?fun_b@CClassA@@UAEXXZ
    DD  FLAT:?fun_c@CClassA@@UAEXXZ
CONST   ENDS

在内存中的情况
第一个函数已经不同,说明基类中的被覆盖

这里写图片描述

objB 的虚函数结构为:

这里写图片描述


多重继承(无虚函数覆盖)

C++代码:

class CClassA
{
public:
    virtual void fun_a(){}
    virtual void fun_b(){}
};
class CClassB 
{
public:
    virtual void fun_c(){}
    virtual void fun_d(){}
};
class CClassC : public CClassA, public CClassB
{
public:
    /*virtual void fun_a(){}
    virtual void fun_c(){}*/
    virtual void fun_e(){}
    virtual void fun_f(){}
};
int main()
{
    CClassA objA;
    CClassB objB;
    CClassC objC;
    return 0;
}

反汇编各个类的虚函数表:

  • CLassC (有两个虚函数表):
    可以看到 C 本身 的虚函数被接在第一个继承类 CClassA 的后面
CONST   SEGMENT
??_7CClassC@@6BCClassB@@@ DD FLAT:??_R4CClassC@@6BCClassB@@@ ; CClassC::`vftable'
    DD  FLAT:?fun_c@CClassB@@UAEXXZ
    DD  FLAT:?fun_d@CClassB@@UAEXXZ
CONST   ENDS
CONST   SEGMENT
??_7CClassC@@6BCClassA@@@ DD FLAT:??_R4CClassC@@6BCClassA@@@ ; CClassC::`vftable'
    DD  FLAT:?fun_a@CClassA@@UAEXXZ
    DD  FLAT:?fun_b@CClassA@@UAEXXZ
    DD  FLAT:?fun_e@CClassC@@UAEXXZ
    DD  FLAT:?fun_f@CClassC@@UAEXXZ
CONST   ENDS
  • CClassB :
CONST   SEGMENT
??_7CClassB@@6B@ DD FLAT:??_R4CClassB@@6B@      ; CClassB::`vftable'
    DD  FLAT:?fun_c@CClassB@@UAEXXZ
    DD  FLAT:?fun_d@CClassB@@UAEXXZ
CONST   ENDS
  • CClassA :
CONST   SEGMENT
??_7CClassA@@6B@ DD FLAT:??_R4CClassA@@6B@      ; CClassA::`vftable'
    DD  FLAT:?fun_a@CClassA@@UAEXXZ
    DD  FLAT:?fun_b@CClassA@@UAEXXZ
CONST   ENDS

在内存中查看
objC 的总体情况(两个虚函数指针 vfptr):

这里写图片描述

  • objC 的内存:

这里写图片描述

第一个虚函数表指针 0036CD58H:

这里写图片描述

其中4个地址的内容分别是:(这里也可以看出 C 的虚函数跟在 A 的后面)

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

第二个虚函数表指针 0036CD74H:

这里写图片描述

其中2个地址的内容分别是:(这里就是第二个继承类的虚函数)

这里写图片描述

这里写图片描述

SO , CClassC 的虚表结构:

这里写图片描述


多重继承(有虚函数覆盖)

C++代码:

class CClassA
{
public:
    virtual void fun_a(){}
    virtual void fun_b(){}
};
class CClassB 
{
public:
    virtual void fun_c(){}
    virtual void fun_d(){}
};
class CClassC : public CClassA, public CClassB
{
public:
    virtual void fun_a(){}
    virtual void fun_c(){}
    virtual void fun_e(){}
    virtual void fun_f(){}
};

int main()
{
    CClassA objA;
    CClassB objB;
    CClassC objC;
    return 0;
}

反汇编虚函数表:

  • CClassC:
CONST   SEGMENT
??_7CClassC@@6BCClassB@@@ DD FLAT:??_R4CClassC@@6BCClassB@@@ ; CClassC::`vftable'
    DD  FLAT:?fun_c@CClassC@@UAEXXZ
    DD  FLAT:?fun_d@CClassB@@UAEXXZ
CONST   ENDS

CONST   SEGMENT
??_7CClassC@@6BCClassA@@@ DD FLAT:??_R4CClassC@@6BCClassA@@@ ; CClassC::`vftable'
    DD  FLAT:?fun_a@CClassC@@UAEXXZ
    DD  FLAT:?fun_b@CClassA@@UAEXXZ
    DD  FLAT:?fun_e@CClassC@@UAEXXZ
    DD  FLAT:?fun_f@CClassC@@UAEXXZ
CONST   ENDS
  • CClassB:
CONST   SEGMENT
??_7CClassB@@6B@ DD FLAT:??_R4CClassB@@6B@      ; CClassB::`vftable'
    DD  FLAT:?fun_c@CClassB@@UAEXXZ
    DD  FLAT:?fun_d@CClassB@@UAEXXZ
CONST   ENDS
  • CClassA:
CONST   SEGMENT
??_7CClassA@@6B@ DD FLAT:??_R4CClassA@@6B@      ; CClassA::`vftable'
    DD  FLAT:?fun_a@CClassA@@UAEXXZ
    DD  FLAT:?fun_b@CClassA@@UAEXXZ
CONST   ENDS

在内存中查看
objC 的内存:

这里写图片描述

第一个虚表:

这里写图片描述

对应的函数:

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

第二个虚表内容:

这里写图片描述

对应的函数:

这里写图片描述

这里写图片描述

SO , CClassC 的虚表结构:

这里写图片描述

值得注意的是,如果基类中有数据成员被继承,那么 CClassC 的对象的模型应该是这样的:

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值