1.直接看下列代码:
#include <iostream> using namespace std; class base{ public: void who(){ cout<<"this is the class of base!"<<endl; } }; class derivel1:public base{ public: void who(){ //一般的重载函数 cout<<"this is the class of derivel1!"<<endl; } }; class derivel2:public base{ public: void who(){ cout<<"this is the class of derivel2!"<<endl; } }; int main(){ base obj1,*p; derivel1 obj2; derivel2 obj3; p=&obj1; p->who(); p=&obj2; p->who(); ((derivel1*)p)->who(); p=&obj3; p->who(); ((derivel2*)p)->who(); obj2.who(); obj3.who(); return 0; }
这就引入了为什么要引入虚函数的概念——————为了实现多态性
2.对于虚函数在内存中的分布,看一下博客即可深刻体会:
http://blog.csdn.net/zhangliang_218/article/details/5544802
ps:注意虚函数和重载函数的关系
ps:注意与java多态的区别
3.在构造函数和析构函数中调用虚函数
编译系统对构造函数和析构函数中调用虚函数采用静态联编,即它们所调用的虚函数是自己的类或者基类中定义的函数而不是在任何派生类中重定义的函数。
例子如下:
#include <iostream> using namespace std; class base{ public: base(){ } virtual void vf(){ cout<<"base::vf() called"<<endl; } }; class son:public base{ public: son(){ vf(); } void g(){ vf(); } }; class grandson:public son{ public: grandson(){ } void vf(){ cout<<"grandson::vf() called "; } }; int main(){ grandson gs; gs.g(); return 0; }
结果如下:
程序出现这样的运行结果是因为在建立grandson类的对象gs时,它所包含的基类子对象在派生类中定义的新成员建立之前就被建立。
4.空的虚函数
派生类并不一定必须实现基类中的虚函数,如果派生类想通过虚函数机制访问虚函数,则必须建立一条从基类到派生类的虚函数路径。
#include <iostream> using namespace std; class base{ public: virtual void print(){ cout<<"class base "; } }; class son:public base{ public: virtual void print(){ //空虚函数 } }; class grandson:public son{ public: virtual void print(){ cout<<"class grandson! "; } }; void show(base *p){ p->print(); } int main(){ base *pbase=new base; son *pson=new son; grandson *pgrandson=new grandson; show(pbase); show(pson); show(pgrandson); return 0; }
运行结果:
5.纯虚函数和抽象类