关于虚函数(一)

   此篇只写最基本的概念.

   1.什么是虚函数?

   2.为什么会有虚函数?(虚函数的作用)

   3.虚函数是如何实现的?


1.首先说什么是虚函数?

定义: 虚函数必须是基类的非静态成员函数.

格式如下:

  virtual  函数返回值类型  虚函数名(形参表) {函数体}

这里注意,用词,必须是基类中并且是非静态成员函数.也就是说虚函数不能用static关键字修饰,也不能是构造函数或者是友元函数.

2.为什么会有虚函数?

这里要先说说C++面向对象的三个特征:封装,继承,多态.下面只说说多态.C++里的多态,多态是指支持相关的对象具有不同的成员函数(原型相同),并允许对象与适当的成员函数进行运行时绑定.注意这句话里的具有不同的成员函数(原型相同), 可以发现多态是通过继承机制而实现的.有时无法在编译时分辨所拥有的对象到底是基类对象还是派生类对象.因此会在运行期进行绑定,也称动态联编.实现这种功能就需要虚函数.多态非常有用,因为这意味着可以给相似的东西取相同的名字.运行时系统在几个名字相同的函数中选择了正确的一个进行调用.(ps:C++的多态有两种:静态的重载和动态的虚函数机制)

3.虚函数是如何实现的?

有虚函数的类内部会有一个叫"虚表"的指针,有多少个虚函数就有多少个指针.每个继承有虚函数的的对象在new时分配一张虚函数表,通过函数指针动态取地址.在C++标准规格说明书中提到,编译器必须保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证正确取到虚函数的偏移量),因此我们可以通过对象变量的地址获取虚函数表的地址.然后可以遍历其中的函数指针,调用相应的函数.

PS:

1.虚函数不能是构造函数的原因:

(1).从存储空间上:虚函数对应一个虚函数表,可是这个虚函数表其实是存储在对象内存空间的,问题是如果构造函数是虚的,就需要通过虚函数表来调用,可是对象还没实例化,也就是内存还没有,怎么找虚函数表呢?因此构造函数不能是虚函数.

(2).从使用角度上:虚函数主要用于信息不全的情况下,能使重载的函数得到合适的调用,构造函数本身就是要初始化实例,那使用虚函数也就没有了意义.所以构造也没必要是虚函数

2.为什么鼓励析构函数设为虚函数?

目的就是delete基类指针的时候把派生类的析构函数也调用了.例如 Fruit *apple = new Apple();delete apple时就可以把派生类Apple中的析构函数也能够得到调用.如果不是Fruit类中的析构函数不设为虚函数,那么派生类Apple中不在Fruit基类中的数据成员就不会被销毁掉造成内存泄露.

#include <iostream>
using namespace std;
class Fruit
{
    public:
    virtual ~Fruit(){cout<<"Fruit destructor---"<<endl;}   //虚函数
};
class Apple:public Apple
{
    public:
    Apple(){cout<<"Apple----constructor---"<<endl;m_p=new char[10];}
    ~Apple(){cout<<"Apple destructor---"<<endl;}
    private:
    char *m_p;
};
int main()
{
    Fruit *apple=new Apple();   //Fruit类型的指针指向了一个B类型的动态对象
    delete apple;     //若Fruit的析构函数不是虚函数,那么delete将会造成内存泄露,只释放了属于Fruit的那部分内存。
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值