C++中虚函数功能的实现机制

  次阅读 作者:智能小宝 来源:互联网 2016-01-19 13:00 我要评论(0)

要理解C++中虚函数是如何工作的,需要回答四个问题。

1、 什么是虚函数。

虚函数由于必须是在类中声明的函数,因此又称为虚方法。所有以virtual修饰符开始的成员函数都成为虚方法。此时注意是virtual修饰的成员函数不是virtual修饰的成员函数名。

例如:基类中定义:

virtual void show(); //由于有virtual修饰因此是虚函数

voidshow(int); //虽然和前面声明的show虚函数同名,但不是虚函数。

所有的虚函数地址都会放在所属类的虚函数表vtbl中。另外在基类中声明为虚函数的成员方法,到达子类时仍然是虚函数,即使子类中重新定义基类虚函数时未使用virtual修饰,该函数地址仍会放在子类的虚函数表vtbl中。

2、 正确区分重载、重写和隐藏。

注意三个概念的适用范围:处在同一个类中的函数才会出现重载。处在父类和子类中的函数才会出现重写和隐藏。

重载:同一类中,函数名相同,但参数列表不同。

重写:父子类中,函数名相同,参数列表相同,且有virtual修饰。

隐藏:父子类中,函数名相同,参数列表相同,但没有virtual修饰;

或:函数名相同,参数列表不同,无论有无virtual修饰都是隐藏。

例如:

基类中:(1) virtual void show(); //是虚函数

(2) void show(int); //不是虚函数

子类中:(3) void show(); //是虚函数

(4) void show(int); //不是虚函数

1,2构成重载,3,4构成重载,1,3构成重写,2,4构成隐藏。另外2,3也会构成隐藏,子类对象无法访问基类的void show(int)成员方法,但是由于子类中4的存在导致了子类对象也可以直接调用void show(int)函数,不过此时调用的函数不在是基类中定义的void show(int)函数2,而是子类中的与3重载的4号函数。

3、 虚函数表是如何创建和继承的。

基类的虚函数表的创建:首先在基类声明中找到所有的虚函数,按照其声明顺序,编码0,1,2,3,4,然后按照此声明顺序为基类创建一个虚函数表,其内容就是指向这些虚函数的函数指针,按照虚函数声明的顺序将这些虚函数的地址填入虚函数表中。例如若show放在虚函数声明的第二位,则在虚函数表中也放在第二位。

对于子类的虚函数表:首先将基类的虚函数表复制到该子类的虚函数表中。若子类重写了基类的虚函数show,则将子类的虚函数表中存放show的函数地址(未重写前存放的是子类的show虚函数的函数地址)更新为重写后函数的函数指针。若子类增加了一些虚函数的声明,则将这些虚函数的地址加到该类虚函数表的后面。

4、 虚函数表是如何访问的。

当执行pBase->show()时,要观察show在Base基类中声明的是虚函数还是非虚函数。若为虚函数将使用动态联编(使用虚函数表决定如何调用函数),若为非虚函数则使用静态联编(根据调用指针pBase的类型来确定调用哪个类的成员函数)。此处假设show为虚函数,首先:由于检查到pBase指针类型所指的类Base中show定义为虚函数,因此找到pBase所指的对象(有可能是Base类型也可能是Extend类型。),访问对象得到该对象所属类的虚函数表地址。其次:查找show在Base类中声明的位置在Base类中所有虚函数声明中的位序。然后到pBase 所指对象的所属类(有可能是Extend哦,多态)的虚函数表中访问该位序的函数指针,从而得到要执行的函数。

例如:

基类Base::virtualvoid show(); (1)

子类Extend::virtualvoid show(); (2)

Externext;

Base*pBase=

pBase->show();

当执行pBase->show();时首先到Base中查看show(),发现其为虚函数,然后访问pBase指向的ext对象,在对象中得到Extend类的虚函数表,在Base类声明中找到show()声明的位序0,访问Extend类的虚函数表的位置0,得到show的函数地址。注意若只有基类定义了virtual void show();而子类未重写virtual void show();即上面的函数(2),则Extend虚函数表中的位序0中存放的地址仍然是Base类中定义的virtual void show()函数,而若Extend类中重写了Base类中的virtual void show()方法,则Extend的虚函数表中位序0的函数地址将被更新为Extend中新重写的函数地址。从而调用pBase->show()时将产生多态的现象。

总结:当调用pBase->show();时,执行的步骤:

本站文章信息来源于网络以及网友投稿,本站只负责对文章进行整理、排版、编辑,是出于传递更多信息之目的,并不意味着赞同其观点或证实其内容的真实性。如果您有什么意见或建议,请联系QQ28-1688-302!

人工智能实验室
相关文章相关文章
  • 韩春雨称已能重复实验结果 近期将有消息公布

    韩春雨称已能重复实验结果 近期将有消息公布

  • 无人驾驶汽车如何改变城市生活?听听他们怎么说

    无人驾驶汽车如何改变城市生活?听听他们怎么说

  • 英国研发“杀生”机器人 通过生命体获取能量

    英国研发“杀生”机器人 通过生命体获取能量

  • 未来两年人工智能要怎么走?看这篇就够了

    未来两年人工智能要怎么走?看这篇就够了

网友点评网友点评
阅读推荐阅读推荐

据国外媒体报道,在过去两年内,聊天机器人(chatbot)、人工智能以及机器学习的研发和采用取得了巨大进展。许多初创公司正利用人工智能和...

霍金 视觉中国 图 英国著名物理学家霍金(Stephen Hawking)再次就人工智能(AI)发声,他认为:对于人类来说,强大AI的出现可能是最美妙的...

文|郑娟娟 今年,人工智能(AI) 60岁了。在AI60岁的时候,笔者想要介绍一下AI100,一个刚刚2岁的研究项目,但它的预设寿命是100年,甚至更长...

AlphaGo与李世石的人机大战,为大众迅速普及了人工智能的概念。 但对谷歌而言,除了下围棋,现在的人工智能进展到哪一步了?未来,人工智能...