python多态原理及实现_c++中多态的实现原理?

题主你肯动脑筋是好的。尽然是考虑指针/引用的对象的类型判断,那为什么还需要虚指针和虚表啊?我只要判断了是调用基类还是派生类不就行了吗?

请你继续思考下去,首先这里有一个问题——你如何知道这个对象是基类还是派生类的对象?

一个很自然的想法就是,我把类型信息保存在一个地方就行了,对吧。

下一个问题——假如要保存,保存什么?

保存类型信息,比如这个对象是“Cat”类的,尽管Cat继承自Animal,但我可以在创建对象的时候把“Cat”记下来,或许不是字符串"Cat",而是某个代表Cat类型的数字。是不是?

保存在哪里?

我们知道一个类可以有很多对象,一个对象的指针或者引用又可以upcast成基类的指针或引用,这么看起来,这“类型信息”必须保存在每一个对象里。不然,我怎么知道Animal *p1, *p2,哪一个是Cat类的,哪一个又是Tiger类的。

好,再下一个问题——假如我这么保存,那么调用这个函数的时候,比如

Animal *p1 = get_an_animal_from_zoo();

p1->Speak();

我们该如何使用刚才保存的那些信息,来调用到正确的函数?

我们刚才假设,我们保存的类型信息是等价于字符串“Cat”的信息。但是现在我们就犯难了,C++是编译成机器指令的呀,我光有个“Cat”,我哪儿知道Speak函数在哪儿——总不见得还能找到某个Implementation.cpp,找到Cat::Speak()所在的那一行去执行一下吧?

既然讲到了C++语言的目标语言是机器指令,我们就需要针对计算机体系结构做一点扫盲了。以x86为例,你调用一个函数,按照一种典型的Calling Convention,编译成机器指令,大致上是长这样的:(引用自 wikipedia)

push EAX ; pass some register result

push byte[EBP+20] ; pass some memory variable (FASM/TASM syntax)

push 3 ; pass some constant

call calc ; the returned result is now in EAX

这里一个很重的信息是:计算机有一个指令寄存器,里面的数字是多少,就表示它下一条执行的指令在哪里。调用函数,无非是先做一些准备工作,以保证函数返回以后程序还能找回来,然后把指令寄存器设置成函数入口的地址。你的cpu自动就会去执行函数。

所以:我们保存了类型信息"Cat"

然而目标代码需要函数Cat::Speak的入口地址

因此,我们必须把类型信息"Cat"转换成Speak的地址,是不是?

那这个用来转换的信息又存在哪儿呢?

...

继续想下去,我们很容易想到,必须在某个地方保存"对象类型" ==> "函数地址"的映射关系,是吧。

C++的设计者觉得,我们未必需要保存”Cat“。我们只要知道“函数地址”在哪里就可以了。我们设计一种机制,每个对象通过这种我们预先设计好的方式、能找到函数地址就行了。从某种程度来说,这种信息起到了等同于“区分指针/引用的对象类型”的作用。

那东西就是虚函数表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值