调用的是派生类中重定义的版本

初学C ,虚函数那有个别感觉蔚成风气啊。C 就是经过虚函数落成了多态。在C 中,以virtual关键字最初的函数是虚函数,虚函数是基类希望派生类实行双重定义的函数,不期望派生类重新定义而浑然世襲的并非定义为虚函数。生龙活虎旦函数在基类中声称为虚函数,派生类就无法修正这么些谜底,派生类中再一次定义虚函数时,关键字virtual无足轻重。

      虚函数产生动态绑定一定要相同的时候知足两个规范:1卡塔尔国那一个函数是虚函数2卡塔尔国必得透过基类类型的引用或指针进行函数的调用。首先要明了一个真相,那便是每一种派生类的指标都包含基类部分,存在从派生类到基类的退换,即能够应用基类类型的指针和援用来援用派生类的指标,由此当使用贰个基类类型的指针或援引时,实际上大家是心余力绌登时确认到底绑定的对象类型是基类的还是派生类的,只可以在运维时规定。当使用基类对象调用虚函数时,调用基类中的虚函数版本,当使用派生类调用时,调用的是派生类中重定义的版本。当想克服虚函数机制时,能够应用成效域操作符举办展示限制。

从学习到面试,个人计算了有关虚函数的几个难题,如下:

1.虚函数表;

2.构造函数行不行是虚函数;

3.static成员函数可不得以是虚函数;

4.C 中虚函数与重载,为啥要用虚函数;

5.纯虚函数

要搞懂2.3标题,首先要驾驭虚函数表的概念和做事原理,以前也读过部分资料,不过否特清晰,找了贰个大牌写的blog,收获相当的大:

而后大家来看看前边难题的回应

2.构造函数行还是不行是虚函数:

answer:

1卡塔 尔(阿拉伯语:قطر‎从下面多涉及的文化,大家得以观看虚函数的进行是通过虚函数表来完结的,由此这几个虚函数表必要求在虚函数调用以前最早化完结。生成三个类的靶子要推行构造函数,而设置VPT纳瓦拉也是在构造函数中成就的。其实在虚函数运维早先,对象的系列应该是一心的。而构造函数实施从前,对象的品类是不完全的。假若构造函数也是虚函数的话,那么VPTTiggo就没人来开始化,不完全的门类的目的也力所不及推行那一个虚的构造函数。2卡塔尔试想一下,虚函数是二个基类中的函数在子类中的重写,借使构造函数成了虚函数,那岂不是派生类中的构造函数名是基类类型的名字?那明摆着是不成立的。

3.static成员函数可以还是不可以是虚函数:

answer:

在虚函数表的规律中,编译器在每一个门类对象里私自的插入了一个VPTRAV4,这一个VPT智跑指向虚函数表。虚成员函数在奉行时能够由此this那些遮盖形参所指对象判定是哪些项指标,再通过虚函数表调用精确版本的函数。而static成员函数无this指针,并且她是静态的,子类世袭后仍然为原先那一个静态的函数,不晤面世多态的施用,所以static函数无法是虚函数。

  1.       重载overload是依照函数的参数列表来采撷要调用的函数版本,而多态是基于运维时对象的实际类型来接受要调用的虚virtual函数版本,多态的兑现是透过派生类对基类的虚virtual函数进行覆盖override来完成的,若派生类未有对基类的虚virtual函数实行覆盖override的话,则派生类会自动三番五次基类的虚virtual函数版本,那时不论基类指针指向的指标是基类型依然派生类型,都会调用基类版本的虚virtual函数;假若派生类对基类的虚virtual函数实行覆盖override的话,则会在运行时根据指标的骨子里类型来筛选要调用的虚virtual函数版本,比方基类指针指向的靶子类型为派生类型,则会调用派生类的虚virtual函数版本,进而实现多态。

      使用多态的本意是要大家在基类中声称函数为virtual,而且是要在派生类中覆盖override基类的虚virtual函数版本,注意,那个时候的函数原型与基类保持后生可畏致,即同名同参数类型;借让你在派生类中新扩大函数版本,你无法经过基类指针动态调用派生类的新的函数版本,那么些新的函数版本只看做派生类的叁个重载版本。依旧同一句话,重载独有在脚下类中有效,不管你是在基类重载的,照旧在派生类中重载的,两个互不牵连。

      重载是静态联编的,多态是动态联编的。进一层表明,重载与指针实际指向的对象类型毫无干系,多态与指针实际指向的指标类型相关。若基类的指针调用派生类的重载版本,C 编绎感到是不法的,C 编绎器只以为基类指针只能调用基类的重载版本,重载只在现阶段类的名字空间功用域内卓有作用,继承会失去重载的性格,当然,若此时的基类指针调用的是一个虚virtual函数,那么它还有恐怕会开展动态接纳基类的虚virtual函数版本依然派生类的虚virtual函数版本来进行具体的操作,那是因而基类指针实际指向的对象类型来做决定的,所以说重载与指针实际指向的指标类型非亲非故,多态与指针实际指向的靶子类型相关。

这里“隐敝”是指使生类的函数屏蔽了与其同名的基类函数,具体法规大家也来做一小结:

       纵然派生类的函数与基类的函数同名,可是参数不一样。这时候,若基类无virtual关键字,基类的函数将被埋伏。(注意别与重载混淆,固然函数名相通参数分化应称之为重载,但此间不可能领悟为重载,因为派生类和基类不在同一名字空间效果域内。这里精通为隐讳)

       即便派生类的函数与基类的函数同名,可是参数分裂。那时,若基类有virtual关键字,基类的函数将被隐式世袭到派生类的vtable中。那时派生类vtable中的函数指向基类版本的函数地址。同期那些新的函数版本增添到派生类中,作为派生类的重载版本。但在基类指针完成多态调用函数方法时,那么些新的派生类函数版本将会被埋伏。

       如果派生类的函数与基类的函数同名,况且参数也风流倜傥致,但是基类函数未有virtual关键字。那个时候,基类的函数被隐形。(注意别与覆盖混淆,这里了然为回避)。

       假如派生类的函数与基类的函数同名,何况参数也一直以来,可是基类函数有virtual关键字。那时候,基类的函数不会被“隐敝”。(在那间,你要清楚为掩瞒哦)。

  1. 纯虚函数

有的时候,基类仅仅看做其派生类的三个接口,而不期望客户实际成立叁个基类的靶子。当时能够在基类中参加起码多少个纯虚函数,使得基类变为抽象基类。纯虚函数在平时的虚函数前面加上=0.当派生类世袭四个空洞基类时,必得得以达成全体的纯虚函数,不然该派生类仍然为二个抽象类,无法创造对象。

 笔者“志在四方”

...

本文由金沙澳门官网-www.js333com-金沙js333com发布于金沙澳门官网计算机,转载请注明出处:调用的是派生类中重定义的版本

您可能还会对下面的文章感兴趣: