为什么我们需要C+中的虚拟函数?

为什么我们需要C+中的虚拟函数?

我正在学习C+,我只是进入了虚拟函数。

根据我在书中和网上所读到的,虚拟函数是基类中的函数,您可以在派生类中重写这些函数。

但是在这本书的早些时候,当我学习基本继承时,我可以在派生类中重写基函数,而不需要使用virtual.

我在这里错过了什么?我知道虚拟函数还有更多,而且它似乎很重要,所以我想弄清楚它到底是什么。我只是在网上找不到一个直截了当的答案。


慕妹3146593
浏览 611回答 3
3回答

红颜莎娜

这是我所理解的,而不仅仅是virtual函数是,但为什么需要它们:假设你有这两门课:class&nbsp;Animal{ &nbsp;&nbsp;&nbsp;&nbsp;public: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;eat()&nbsp;{&nbsp;std::cout&nbsp;<<&nbsp;"I'm&nbsp;eating&nbsp;generic&nbsp;food.";&nbsp;}};class&nbsp;Cat&nbsp;:&nbsp;public&nbsp;Animal{ &nbsp;&nbsp;&nbsp;&nbsp;public: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;eat()&nbsp;{&nbsp;std::cout&nbsp;<<&nbsp;"I'm&nbsp;eating&nbsp;a&nbsp;rat.";&nbsp;}};在你的主要职能中:Animal&nbsp;*animal&nbsp;=&nbsp;new&nbsp;Animal;Cat&nbsp;*cat&nbsp;=&nbsp;new&nbsp;Cat;animal->eat();&nbsp;//&nbsp;Outputs:&nbsp;"I'm&nbsp;eating&nbsp;generic&nbsp;food."cat->eat();&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;Outputs:&nbsp;"I'm&nbsp;eating&nbsp;a&nbsp;rat."到目前为止还不错,对吧?动物吃普通食物,猫吃老鼠,都不吃。virtual.让我们现在稍微改变一下,这样eat()通过一个中间函数(仅在本例中是一个平凡的函数)调用://&nbsp;This&nbsp;can&nbsp;go&nbsp;at&nbsp;the&nbsp;top&nbsp;of&nbsp;the&nbsp;main.cpp&nbsp;filevoid&nbsp;func(Animal&nbsp;*xyz)&nbsp;{&nbsp;xyz->eat();&nbsp;}现在我们的主要职能是:Animal&nbsp;*animal&nbsp;=&nbsp;new&nbsp;Animal;Cat&nbsp;*cat&nbsp;=&nbsp;new&nbsp;Cat;func(animal);&nbsp;//&nbsp;Outputs:&nbsp;"I'm&nbsp;eating&nbsp;generic&nbsp;food."func(cat);&nbsp;&nbsp;&nbsp; &nbsp;//&nbsp;Outputs:&nbsp;"I'm&nbsp;eating&nbsp;generic&nbsp;food."呃哦.。我们经过了一只猫func()但它不会吃老鼠。你应该超载吗func()所以这需要一个Cat*?如果你不得不从动物那里得到更多的动物,它们都需要自己的动物func().解决办法是eat()从Animal对虚拟函数进行分类:class&nbsp;Animal{ &nbsp;&nbsp;&nbsp;&nbsp;public: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;void&nbsp;eat()&nbsp;{&nbsp;std::cout&nbsp;<<&nbsp;"I'm&nbsp;eating&nbsp;generic&nbsp;food.";&nbsp;}};class&nbsp;Cat&nbsp;:&nbsp;public&nbsp;Animal{ &nbsp;&nbsp;&nbsp;&nbsp;public: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;eat()&nbsp;{&nbsp;std::cout&nbsp;<<&nbsp;"I'm&nbsp;eating&nbsp;a&nbsp;rat.";&nbsp;}};主要:func(animal);&nbsp;//&nbsp;Outputs:&nbsp;"I'm&nbsp;eating&nbsp;generic&nbsp;food."func(cat);&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Outputs:&nbsp;"I'm&nbsp;eating&nbsp;a&nbsp;rat."完成了。

慕森卡

如果没有“虚拟”,您就会得到“早期绑定”。在编译时将根据调用的指针的类型来决定方法的实现。与“虚拟”你得到“晚绑定”。在运行时,将根据指向对象的类型来决定该方法的实现,该对象最初是作为什么构造的。根据指向该对象的指针的类型,这不一定是您所想的。class&nbsp;Base{ &nbsp;&nbsp;public: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;Method1&nbsp;()&nbsp;&nbsp;{&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;"Base::Method1"&nbsp;<<&nbsp;std::endl;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;void&nbsp;Method2&nbsp;()&nbsp;&nbsp;{&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;"Base::Method2"&nbsp;<<&nbsp;std::endl;&nbsp;&nbsp;}};class&nbsp;Derived&nbsp;:&nbsp;public&nbsp;Base{ &nbsp;&nbsp;public: &nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;Method1&nbsp;()&nbsp;&nbsp;{&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;"Derived::Method1"&nbsp;<<&nbsp;std::endl;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;Method2&nbsp;()&nbsp;&nbsp;{&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;"Derived::Method2"&nbsp;<<&nbsp;std::endl;&nbsp;&nbsp;}};Base*&nbsp;obj&nbsp;=&nbsp;new&nbsp;Derived&nbsp;(); &nbsp;&nbsp;//&nbsp;&nbsp;Note&nbsp;-&nbsp;constructed&nbsp;as&nbsp;Derived,&nbsp;but&nbsp;pointer&nbsp;stored&nbsp;as&nbsp;Base*obj->Method1&nbsp;();&nbsp;&nbsp;//&nbsp;&nbsp;Prints&nbsp;"Base::Method1"obj->Method2&nbsp;();&nbsp; &nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;Prints&nbsp;"Derived::Method2"编辑-见这个问题.也-本教程涵盖早期和后期的C+绑定。
打开App,查看更多内容
随时随地看视频慕课网APP