c语言多态的概念(C类和对象)(1)

c语言多态的概念(C类和对象)(2)

然后我们再去看c 中,多态实现的原理.

前面我们说,多态有,静态多态和动态多态,然后并且使用了一下多态,做了个案例.

c语言多态的概念(C类和对象)(3)

c语言多态的概念(C类和对象)(4)

并且我们说,多态的实现需要满足条件,就是首先要有继承关系,要有父类,子类,

然后子类还要必须去重写父类中的虚函数,不重写虚函数的话,那叫做,函数地址早绑定.对吧.

然后要使用多态的话,需要让父类的指针或者引用,指向子类的对象对吧.

并且我们提出了,重写的概念.

c语言多态的概念(C类和对象)(5)

c语言多态的概念(C类和对象)(6)

然后我们通过例子去看,多态的实现原理.

首先去看,上节课我们用到的这个Animal类,然后

里面有个spreak这个,虚函数.这个animal类就是我们的父类.

c语言多态的概念(C类和对象)(7)

c语言多态的概念(C类和对象)(8)

然后我们再去看,上面这个猫类,它继承了父类animal类,

Cat类中重写了,父类Animal类中的spreak()方法.

c语言多态的概念(C类和对象)(9)

c语言多态的概念(C类和对象)(10)

然后狗类,也重写了animal中的spreak方法.

c语言多态的概念(C类和对象)(11)

c语言多态的概念(C类和对象)(12)

然后上面我们就是,通过地址晚绑定,动态多态的方式,实现了

我们给doSpreak方法,传入我们的子类对象,用父类引用来接收,实现对

子类中的重写方法的调用.

那么这个过程的原理是什么?

c语言多态的概念(C类和对象)(13)

c语言多态的概念(C类和对象)(14)

首先我们 去写个test02方法,然后,调用test02方法,打印Animal类的size,大小.

c语言多态的概念(C类和对象)(15)

c语言多态的概念(C类和对象)(16)

首先我们去,打印animal这个父类的大小,但是打印之前我们先把

父类中的,spreak函数,前面的virtual,关键字,给删除掉.

我们再去打印.

c语言多态的概念(C类和对象)(17)

c语言多态的概念(C类和对象)(18)

执行可以看到,只有个函数的地址对吧,可以看到animal这个时候的

大小是一个字节.用来区分对象用的.

c语言多态的概念(C类和对象)(19)

c语言多态的概念(C类和对象)(20)

然后如果我们在animal类的spreak方法前面,加上virtual这个关键字,然后再去打印.

c语言多态的概念(C类和对象)(21)

c语言多态的概念(C类和对象)(22)

我们再去看看,结果是4个字节了. 那么这4个字节是什么呢?

int float是4个字节?对吧 ....指针也是4个字节.

对这个4个字节,其实就是指针.

c语言多态的概念(C类和对象)(23)

c语言多态的概念(C类和对象)(24)

我们去看原理,当我们在Animal类中的spreak函数,前面,添加virtual关键字的时候,

我们可以看到,这个时候Animal类的内部结构是上面,右边这样的.

首先Animal中会有一个vfptr,这个指针,这个指针vfptr的意思是

v - virtual

f-function

ptr - pointer

是虚函数指针的意思.

然后这个vfptr指向的是vftable,这个虚函数表,这个表是干什么用的呢?

这个表是记录了虚函数的地址.

c语言多态的概念(C类和对象)(25)

c语言多态的概念(C类和对象)(26)

比如,我们去看animal类的内部结构,可以看到,当我们在父类animal类中,的spreak函数的前面

添加virtual关键字的时候,他会产生一个vfptr,这个指针,这个指针会指向vftable一个虚函数表的地址,

然后这个表中,这个时候会存放animal类的,虚函数spreak()的地址,也就是&Animal::spreak.

当我们再去写一个Cat类,来继承这个Animal类的时候,在Cat这个子类中,去重写Animal类中的spreak函数,

可以看到由于cat类继承了Animal类,所以,在Cat类的结构中,也有个vfptr,然后这个vfptr,也是指向一个vftable表

,然后这个vftable表中,也是存放了一个&Animal::spreak 这个父类的spreak方法的指针,这个是继承过来的.

c语言多态的概念(C类和对象)(27)

c语言多态的概念(C类和对象)(28)

然后这一步很重要,可以看到由于Cat重写了父类中的spreak函数,所以,在Cat类的内部结构中的vftable,虚函数表中

继承过来的&Animal::spreak函数的地址,就会被替换成&Cat::spreak

而这个过程是在,当我们,调用doSpreak,给参数Animal这个父类的引用,传递一个cat这个子类对象的时候,

发生的.

c语言多态的概念(C类和对象)(29)

c语言多态的概念(C类和对象)(30)

可以看到上面也说了,当父类的指针,或者引用,指向子类的对象的时候,就会发生多态,实际上就是,

会把继承过来的,父类的&Animal::spreak,这个虚函数的指针替换成,

&Cat::spreak,这个子类的spreak的地址.

这样就可以实现,我们执行的时候,传入的是子类的对象,打印出来,就是子类对象中,重写的那个spreak方法的内容了.

c语言多态的概念(C类和对象)(31)

c语言多态的概念(C类和对象)(32)

我们也可以打开工具去看一下具体情况.

c语言多态的概念(C类和对象)(33)

c语言多态的概念(C类和对象)(34)

首先我们去把virtual,关键字,删除掉.

c语言多态的概念(C类和对象)(35)

c语言多态的概念(C类和对象)(36)

可以看到,我们暂时把父类的虚函数spreak,前面的virtual删除掉.

c语言多态的概念(C类和对象)(37)

c语言多态的概念(C类和对象)(38)

我们找到对应的代码文件

c语言多态的概念(C类和对象)(39)

c语言多态的概念(C类和对象)(40)

c语言多态的概念(C类和对象)(41)

用工具,走到对应文件,目录,先查看一下,

c语言多态的概念(C类和对象)(42)

c语言多态的概念(C类和对象)(43)

然后我们,执行

cl /dl reportSingleClassLayoutAnimal "01 多态基本概念.cpp"

c语言多态的概念(C类和对象)(44)

c语言多态的概念(C类和对象)(45)

执行以后,可以看到这个时候如果我们不给父类的spreak函数,前面,添加virtual的情况,可以看到这个时候

animal类的大小是

size(1);1个字节.

c语言多态的概念(C类和对象)(46)

c语言多态的概念(C类和对象)(47)

然后我们再去打开,

animal类中的spreak方法,前面的virtual,然后再去用工具去查看一下Animal类的,结构

可以看到这个我时候size变成了4个字节,然后,里面有vfptr,然后vfptr指针,指向

vftable这个虚函数表,然后可以看到虚函数表中,存着&Animal::spreak这个指针.对吧.

c语言多态的概念(C类和对象)(48)

c语言多态的概念(C类和对象)(49)

我们可以对着去看看,可以看到在Animal类中,当spreak前面加上virtual关键字的时候,类的结构就会有vfptr这个指针,然后

这个指针指向一个vftable这个虚函数表,然后

这个虚函数表中存放着&Animal::spreak这个父类中spreak函数的指针.

c语言多态的概念(C类和对象)(50)

c语言多态的概念(C类和对象)(51)

然后我们再去看看,当我们把Cat类中的,重写的父类中的这个spreak函数,删除掉.

c语言多态的概念(C类和对象)(52)

c语言多态的概念(C类和对象)(53)

我们去查看Cat类的,对象结构去.

c语言多态的概念(C类和对象)(54)

c语言多态的概念(C类和对象)(55)

可以看到这个时候得到的结构,Cat类的大小是字节4个.里面有个vfptr指针,

这个指针指向一个vftable虚函数表,然后

虚函数表,中存放了&Animal::spreak,这个父类的spreak函数的指针对吧.

因为我们在子类中没有重写父类的spreak函数.所以这里,Cat类的虚函数表中,存放的是继承过来的,父类的

&Animal::spreak函数的指针.

c语言多态的概念(C类和对象)(56)

c语言多态的概念(C类和对象)(57)

当我们把Cat类中的,重写了父类中的是spreak的函数的注释打开,然后我们再去执行分析一下.

c语言多态的概念(C类和对象)(58)

c语言多态的概念(C类和对象)(59)

可以看到这个时候

Cat类,的size大小还是4个字节,存放了vfptr,这个指针,然后这个指针指向了vftable,这个虚函数表

然后这个虚函数表中,注意,这时候,存放的指针,就是

&Cat::spreak,这个Cat子类中的spreak函数了.

,