虚函数是怎么做到实现多态性的
什么是实偶函数和虚偶函数?
什么是实偶函数和虚偶函数?
一般地,如果对于函数f(x)的定义域内任意的一个x,都有f(-x)f(x),那么函数f(x)就叫做实偶函数(Even Function)。实偶函数的定义域必须关于y轴对称,否则不能称为实偶函数。
那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异,而采用不同的策略。偶函数
定义域关于y轴对称的函数
一般地,如果对于函数f(x)的定义域内任意的一个x,都有f(x)f(-x),那么函数f(x)就叫做偶函数(EvenFunction
怎么样理解C#中的virtual(虚方法)?
首先你如果不用virtual重写的话,系统默认会为你加new关键字,他的作用是覆盖,而virtual的关键作用在于实现多态,理解一下多态你就会明白为什么这么用了,对于日后软件版本的升级,实现版本兼容性,甚至于扩展都非常重要
什么是虚函数?
虚函数定义:如果在基类中将某个函数指定为并且派生类中有另外一个该函数的定义,则编译器将知道我们不想静态连接该函数。我们真正需要的是基于调用该函数的对象种类,在程序的特定位置选择调用哪一个函数。
作用:虚函数的作用用专业术语来解释就是实现多态性,多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异,而采用不同的策略。
c 是如何实现多继承带来的多态问题?
多态是指同样的消息被不同类型的对象接收时导致完全不同的的行为。有虚函数的类才能叫多态类型的类,可以从探索虚函数是如何实现动态绑定的来了解如何实现多继承中的多态。
单继承时虚函数动态绑定的实现原理每个类各有一个虚表(虚函数表),虚表的内容是由编译器安排的。c 语言并没有规定虚函数表的内容。派生类的虚表中,基类声明的虚函数对应的指针放在前面,派生类新增的虚函数的对应指针放在后面,这样一个虚函数 的指针在基类虚表和派生类虚表中具有相同的位置。每个多态类型的对象中都有一个指 向当前类型的虚表的指针,该指针在构造函数中被赋值。当通过基类的指针或引用调用 一 个虚函数时,就可以通过虚表指针找到该对象的虚表,进而找到存放该虚函数的指针的虚表条目。将该条目中存放的指针读出后,就可获得应当被调用的函数的入口地址,然后 调用该虚函数,虚函数的动态绑定就是这样完成的。
如下图所示:
由上图可以看到基类Base有f(),g()函数,派生类还有新增的h()函数,那么这种单继承的虚函数实现动态绑定的方式是这样的:
从这张超大图片可以看到,每个Base对象都有一个指向Base的虚表的指针,虚表存放着指向每个函数的指针,这些指针存放着对应函数的地址,这样通过虚表指针就能找到虚表,通过虚表就能找到函数指针,通过函数指针就能找到函数,这样虚函数的动态绑定就完成了。派生类Base2也一样。
温馨提示:执行一个类的构造函数时,首先被执行的是基类的构造函数,因此构造一个派生类的对象时,该对象的虚表指针首先会被指向基类的虚表。只有当基类构造函数执行完后,虚表指针才会被指向派生类的虚表,这就是基类构造函数调用虚函数时不会调用派生类的虚函数的原因。
在多继承时,情况会变得更加复杂,因为在多继承时,情况会更加复杂,因为每个基类都有各自的虚函数,这样继承了多个基类的派生类需要多个虚表(或一个虚表分为多段,每个基类的虚表指针指向其中一段的地址。因为有些编译器把多个虚表连成一个)如图所示:
派生类Base3公有继承了Base,Base2,那么虚函数动态绑定的实现方式是这样的:
提示:多重继承时,派生类新增的成员放在第一个表,比如上图Base3()的虚表的m()指针。
事实上,一个类的虚表中存放的不只是虚函数的指针,用于支持运行时类型识别的对象的运行时类型信息也需要通过虚表来访问,只有多态类型有虚表,因此只有多态类型支持运行时类型识别。
以上就是我的回答,有不同意见的欢迎来讨论,喜欢我的回答请关注,我们一起学习。