C++语言虚函数实现多态的原理

论坛 期权论坛 期权     
java那些事   2019-7-14 05:18   3276   0



自上一个帖子之间跳过了一篇总结性的帖子,之后再发,今天主要研究了c++语言当中虚函数对多态的实现,感叹于c++设计者的精妙绝伦

C++中虚函数表的作用主要是实现了多态的机制。首先先解释一下多态的概念,多态是C++的特点之一,关于多态,简而言之就是 用父类的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。

这种方法呢,可以让父类的指针具有多种形态,也就是说不需要改动很多的代码就可以让父类这一种指针,干一些很多子类指针的事情,这里是从虚函数的实现机制层面进行研究

在写这篇帖子之前对于相关的文章进行了查阅,基本上是大段的文字,所以我的这一篇可能会用大量的图形进行赘述(如果理解有误的地方,烦请大佬能够指出),

接下来就言归正传:
首先介绍一下为什么会引进多态呢,基于c++的复用性和拓展性而言,同类的程序模块进行大量重复,是一件无法容忍的事情,比如我设置了苹果,香蕉,西瓜类,现在想把这些东西都装到碗这个函数里,那么在主函数当中,声明对象是必须的,但是每一次装进碗里对于水果来说,都要用自己的指针调用一次装的功能。

那为什么不把这些类抽象成一个水果类呢,直接定义一个水果类的指针一次性调用所有水果装的功能呢,这个就是利用父类指针去调用子类成员,但是这个思想受到了指针指向类型的限制,也就是说表面指针指向了子类成员。

但实际上还是只能调用子类成员里的父类成员,这样的思想就变的毫无意义了,如果想要解决这个问题,只要在父类前加上virtual就可以解决了,这里就是利用虚函数实现多态的实例。

首先还是作为举例来两个类,在之前基础知识的帖子中提到过,空类的大小是一个字节(占位符),函数,静态变量都在编译期就形成了,不用类去分配空间,但是做一个小实验,看一看在定义了虚函数之后,类的大小是多少呢

#include
using namespace std;
class CFather
{
public:
    virtual void AA()  //虚函数标识符
    {
        cout g(); //Base2::g()

  b3->g(); //Base3::g()
以上就是对多继承情况的一种讨论


那么再看看如何在代码的层面上来验证原理呢?

首先在主函数内声明了一个父类的指针,指向子类对象,那么这个对这个父类指针解引用的话,就能得到一个vfptr指针,和父类,子类对象,但是现在我只需要指向虚函数的指针,那么就可以定义指针只取前四个字节,利用强转,*(int *)p 这个得到了vfptr的地址。

那么继续想要获得虚函数表中的虚函数,就是再次解引用了,但是如何进行偏移呢?在整形,浮点型里,指针的偏移量都是指针指向类型所觉得的,而这里是个函数指针,函数指针不允许利用指针指向类型来进行偏移量的取值。

因为函数的类型大小是不确定的,但是我们知道,虚函数表里都是函数指针,指针的大小是确定的都是四个字节,那还可以继续利用强转,控制指针每次偏移四个字节,那么这个时候再进行解引用就是我们所取得函数的地址了,如果语言太赘述的话,可以看下面的例子

//--------------------------------------------------
#include
using namespace std;


class CFather
{
public:
    virtual void AA()
    {
        cout
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:15
帖子:3
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP