关于C++中虚函数的作用

来源:互联网 发布:淘宝手机上架 编辑:程序博客网 时间:2024/05/05 19:03

昨天去面试,面试官问道:虚函数有什么作用,我解释了半天也没解释清楚,其实说到底还是理解不够深刻,或者说简直没什么理解,连子类重写父类的普通函数和子类重写父类的虚函数的区别都不知道,真是弱爆了!!1

虚函数的作用:通过以下两个程序来进行解释!

可以让成员函数操作一般化,用基类的指针指向不同的派生类的对象时, 
基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数, 
而不是基类中定义的成员函数(只要派生类改写了该成员函数)。 
若不是虚函数,则不管基类指针指向的哪个派生类对象,调用时都 
会调用基类中定义的那个函数。

程序1:

#include <iostream>
using namecpace std;
class B0 //基类B0声明

public:

 void display(){cout<<"B0::display()"<<endl;} //公有成员函数
};
class B1: public B0 
{
 public:
  void display(){cout<<"B1::display()"<<endl;} 
};
class D1: public B1 
{
public:
  void display(){cout<<"D1::display()"<<endl;} 
};
void fun(B0 *ptr) 
{

 ptr->display(); //"对象指针->成员名"  

}
void main() //主函数

B0 b0; //声明B0类对象
 B1 b1; //声明B1类对象
 D1 d1; //声明D1类对象
 B0 *p; //声明B0类指针
 p=&b0; //B0类指针指向B0类对象
 fun(p);
 p=&b1; //B0类指针指向B1类对象
 fun(p);
 p=&d1; //B0类指针指向D1类对象
 fun(p);
}
运行结果:
B0::display()
B0::display()
B0::display()

程序2:
#include <iostream>
using namespace std;
class B0 //基类B0声明
{public: //外部接口
 virtual void display() //虚成员函数
     {cout<<"B0::display()"<<endl;} 
};
class B1: public B0 //公有派生
{ public:
       void display()  {  cout<<"B1::display()"<<endl;  }
};
class D1: public B1 //公有派生
{ public:
   void display() {  cout<<"D1::display()"<<endl;  }
};
void fun(B0 *ptr) //普通函数
{    ptr->display();    }
void main() //主函数
{ B0 b0,  *p; //声明基类对象和指针
 B1 b1; //声明派生类对象
 D1 d1; //声明派生类对象
 p=&b0;
 fun(p); //调用基类B0函数成员
 p=&b1;
 fun(p); //调用派生类B1函数成员
 p=&d1;
 fun(p); //调用派生类D1函数成员
}
运行结果:
B0::display()
B1::display()
D1::display()

虚函数是动态绑定的基础。
是非静态的成员函数。
在类的声明中,在函数原型之前写virtual。
virtual 只用来说明类声明中的原型,不能用在函数实现时。
具有继承性,基类中声明了虚函数,派生类中无论是否说明,同原型函数都自动为虚函数。
本质:不是重载声明而是覆盖。
调用方式:通过基类指针或引用,执行时会根据指针指向的对象的类,决定调用哪个函数。

到这个地方还没完,其实完全可以不用父类类型的指针,直接创建子类对象来调用子类的普通函数也是可以的啊,为什么非要使用虚函数呢?

虽然这样说,但是实际开发过程中不是这样的,当我们使用一些类库、框架的时候,这些类库、框架是事先就写好的。我们在使用的时候不能直接修改类库的源码,我们只能派生类库中的类来覆盖一些成员函数以实现我们的功能,但这些成员函数有的是由框架调用的。这种情况下,用虚函数是很好的办法。


0 0