虚函数的总结

1。虚函数的定义

     虚函数是为了更好的实现OO思想的多态性而引入的,即当父类指针指向不同的对象(属于子类或父类)时,调用的将是对象所属类定义的该函数的版本。也就是说同一语句在不同环境下产生不同的效果。

下面是验证代码:

#include <iostream.h>
class myParentsClass
{
    public:
    myParentsClass()
    {
        cout<<"myParentsClass::myParentsClass"<<endl;
    }
   
    void testFun()
    {
        cout<<"myParentsClass::testFun"<<endl;
        fun();
    }

  virtual void fun()
    {
        cout<<"myParentsClass::fun()"<<endl;
    }
~myParentsClass()
    {
        cout<<"myParentsClass::~myParentsClass"<<endl;
    }

};

class myClass:public myParentsClass
{
    public:
    myClass()
    {
        cout<<"myClass::myClass"<<endl;
    }
     void fun()
    {
        cout<<"myClass::fun()"<<endl;
    }
    ~myClass()
    {
        cout<<"myClass::~myClass"<<endl;
    }

};

class mySonClass:public myClass
{
    public:
    mySonClass()
    {
        cout<<"mySonClass::mySonClass"<<endl;
    }
   void fun()
    {
        cout<<"mySonClass::fun()"<<endl;
    }
    ~mySonClass()
    {
        cout<<"mySonClass::~mySonClass"<<endl;
    }

};

int main()
{
   myParentsClass *pClass=NULL;
   myClass *pMe=NULL;

  myParentsClass myParents;
    myClass me;
     mySonClass mySon;
    // pMe=&myParents;    //出错,子类指针不能指向父类对象
     pClass=&myParents;
     pClass->fun();
     pClass=&me;
     pClass->fun();
     pClass=&mySon;
     pClass->fun();

return 0;
}

什么时候适合定义某个函数为虚函数呢?

以上例子得出结论的是 该函数将要在子类中进行改写时

2。虚函数的传递性:

虚函数只向下传递并且不会产生中断,即不会因为子类中没有对虚函数定义而影响该子类的子类同名函数的虚特性。

首先验证 向下传递性质

在主函数中加入如下语句:

........

pMe=&mySon;

pMe->fun();   //具有虚特性,调用的是mySonClass的fun方法

.....

然后验证  不会中断

去掉fun()在myClass的定义.并再次定义一个子类如下:

class myGrandsonClass:pulblic mySonClass
{
    public:
    void fun()
    {
        cout<<"myGrandsonClass::fun()"<<endl;
    }
};

在主函数中加入如下语句:

.........

  mySonClass *pSon=NULL;
     myGrandsonClass myGrandson;
     pSon=&myGrandson;
     pSon->fun();    //可以看到虚函数的特性并没有消失

...........

最后验证虚函数不具备向上传递的特性:

去掉myParentsClass中fun()的修饰符virtual,然后在myClass或者在mySonClass中的fun()前面加上virtual

观察结果。

然后在主函数中加入如下语句:

 pMe=&mySon;//只在mySonClass中的fun()的前面加virtual

    pMe->fun();

观察结果。

3.虚函数的其他应用

在主函数加入如下代码:

................

 pClass=&myParents;
     pClass->fun();
     pClass->testFun();
     pClass=&me;
     pClass->fun();
      pClass->testFun();
     pClass=&mySon;
     pClass->fun();
      pClass->testFun();

.......................

观察结果可以发现:

testFun()方法也在随指针的指向改变而调用不同的fun()函数。而当去掉fun()前面的virtual时,结果又会不同

由此得出以下结论:

     void testFun()
    {
        cout<<"myParentsClass::testFun"<<endl;
        fun();     //这个地方默认是的实际上是this->fun()
                   //而不是myParentsClass::fun()
    }

ps:对于理解  深入浅出MFC第三章会有帮助

又:在主函数中加入如下语句:

myParentsClass *pParents=new myClass();

delete pParents;

pParents=NULL;

观察结果。

可以发现 delete pParents;  并没有调用myParentsClass的析构函数。如果该析构函数负责一些该类动态分配的内存的回收的话,这个语句将会造成严重的后果(指针悬挂).

解决办法:把myParentsClass的析构函数声明为虚函数。

当然如果你并没有打算在子类或子类的子类中重新定义该类(子类....)的析构函数也就不用这末做了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值