欢迎来到天天文库
浏览记录
ID:46599522
大小:50.50 KB
页数:5页
时间:2019-11-26
《虚函数-从零开始》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
1、虚函数:从零开始(转)虚函数联系到多态,多态联系到继承。所以本文中都是在继承层次上做文章。没了继承,什么都没得谈。下面是小弟对C++的虚函数这玩意儿的理解。一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始)简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。下面来看一段简单的代码classA{public: voidprint(){
2、cout<<”ThisisA”<3、就是一切用指向基类的指针或引用来操作对象。那现在就把main()处的代码改一改。intmain(){ //main2 Aa; Bb; A*p1=&a; A*p2=&b; p1->print(); p2->print();}运行一下看看结果,哟呵,蓦然回首,结果却是两个ThisisA。问题来了,p2明明指向的是classB的对象但却是调用的classA的print()函数,这不是我们所期望的结果,那么解决这个问题就需要用到虚函数classA{public: virtualvoidprint(){cout<<”ThisisA”4、<5、现在重新运行main2的代码,这样输出的结果就是ThisisA和ThisisB了。现在来消化一下,我作个简单的总结,指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。 二, 虚函数是如何做到的(如果你没有看过《InsideTheC++ObjectModel》这本书,但又急切想知道,那你就应该从这里开始)虚函数是如何做到因对象的不同而调用其相应的函数的呢?现在我们就来剖析虚函数。我们先定义两个类classA{ //虚函数示例代码public: virtualvoidfun(){cout<<1<6、;} virtualvoidfun2(){cout<<2<7、上图,可以看到这两个vtbl分别为classA和classB服务。现在有了这个模型之后,我们来分析下面的代码A*p=newA;p->fun();毫无疑问,调用了A::fun(),但是A::fun()是如何被调用的呢?它像普通函数那样直接跳转到函数的代码处吗?No,其实是这样的,首先是取出vptr的值,这个值就是vtbl的地址,再根据这个值来到vtbl这里,由于调用的函数A::fun()是第一个虚函数,所以取出vtbl第一个slot里的值,这个值就是A::fun()的地址了,最后调用这个函数。现在我们可以看出来了,只要vptr不同,指向的vtbl就不同,8、而不同的vtbl里装着对应类的虚函数地址,所以这样虚函数就可以完成它的任务。而对于classA
3、就是一切用指向基类的指针或引用来操作对象。那现在就把main()处的代码改一改。intmain(){ //main2 Aa; Bb; A*p1=&a; A*p2=&b; p1->print(); p2->print();}运行一下看看结果,哟呵,蓦然回首,结果却是两个ThisisA。问题来了,p2明明指向的是classB的对象但却是调用的classA的print()函数,这不是我们所期望的结果,那么解决这个问题就需要用到虚函数classA{public: virtualvoidprint(){cout<<”ThisisA”
4、<5、现在重新运行main2的代码,这样输出的结果就是ThisisA和ThisisB了。现在来消化一下,我作个简单的总结,指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。 二, 虚函数是如何做到的(如果你没有看过《InsideTheC++ObjectModel》这本书,但又急切想知道,那你就应该从这里开始)虚函数是如何做到因对象的不同而调用其相应的函数的呢?现在我们就来剖析虚函数。我们先定义两个类classA{ //虚函数示例代码public: virtualvoidfun(){cout<<1<6、;} virtualvoidfun2(){cout<<2<7、上图,可以看到这两个vtbl分别为classA和classB服务。现在有了这个模型之后,我们来分析下面的代码A*p=newA;p->fun();毫无疑问,调用了A::fun(),但是A::fun()是如何被调用的呢?它像普通函数那样直接跳转到函数的代码处吗?No,其实是这样的,首先是取出vptr的值,这个值就是vtbl的地址,再根据这个值来到vtbl这里,由于调用的函数A::fun()是第一个虚函数,所以取出vtbl第一个slot里的值,这个值就是A::fun()的地址了,最后调用这个函数。现在我们可以看出来了,只要vptr不同,指向的vtbl就不同,8、而不同的vtbl里装着对应类的虚函数地址,所以这样虚函数就可以完成它的任务。而对于classA
5、现在重新运行main2的代码,这样输出的结果就是ThisisA和ThisisB了。现在来消化一下,我作个简单的总结,指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。 二, 虚函数是如何做到的(如果你没有看过《InsideTheC++ObjectModel》这本书,但又急切想知道,那你就应该从这里开始)虚函数是如何做到因对象的不同而调用其相应的函数的呢?现在我们就来剖析虚函数。我们先定义两个类classA{ //虚函数示例代码public: virtualvoidfun(){cout<<1<6、;} virtualvoidfun2(){cout<<2<7、上图,可以看到这两个vtbl分别为classA和classB服务。现在有了这个模型之后,我们来分析下面的代码A*p=newA;p->fun();毫无疑问,调用了A::fun(),但是A::fun()是如何被调用的呢?它像普通函数那样直接跳转到函数的代码处吗?No,其实是这样的,首先是取出vptr的值,这个值就是vtbl的地址,再根据这个值来到vtbl这里,由于调用的函数A::fun()是第一个虚函数,所以取出vtbl第一个slot里的值,这个值就是A::fun()的地址了,最后调用这个函数。现在我们可以看出来了,只要vptr不同,指向的vtbl就不同,8、而不同的vtbl里装着对应类的虚函数地址,所以这样虚函数就可以完成它的任务。而对于classA
6、;} virtualvoidfun2(){cout<<2<7、上图,可以看到这两个vtbl分别为classA和classB服务。现在有了这个模型之后,我们来分析下面的代码A*p=newA;p->fun();毫无疑问,调用了A::fun(),但是A::fun()是如何被调用的呢?它像普通函数那样直接跳转到函数的代码处吗?No,其实是这样的,首先是取出vptr的值,这个值就是vtbl的地址,再根据这个值来到vtbl这里,由于调用的函数A::fun()是第一个虚函数,所以取出vtbl第一个slot里的值,这个值就是A::fun()的地址了,最后调用这个函数。现在我们可以看出来了,只要vptr不同,指向的vtbl就不同,8、而不同的vtbl里装着对应类的虚函数地址,所以这样虚函数就可以完成它的任务。而对于classA
7、上图,可以看到这两个vtbl分别为classA和classB服务。现在有了这个模型之后,我们来分析下面的代码A*p=newA;p->fun();毫无疑问,调用了A::fun(),但是A::fun()是如何被调用的呢?它像普通函数那样直接跳转到函数的代码处吗?No,其实是这样的,首先是取出vptr的值,这个值就是vtbl的地址,再根据这个值来到vtbl这里,由于调用的函数A::fun()是第一个虚函数,所以取出vtbl第一个slot里的值,这个值就是A::fun()的地址了,最后调用这个函数。现在我们可以看出来了,只要vptr不同,指向的vtbl就不同,
8、而不同的vtbl里装着对应类的虚函数地址,所以这样虚函数就可以完成它的任务。而对于classA
此文档下载收益归作者所有