关于构造函数 析构函数和虚函数的关系

来源:互联网 发布:java初级编程题 编辑:程序博客网 时间:2024/04/27 23:14

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wangyadong/archive/2009/05/01/4138767.aspx

 

构造函数不能声明为虚函数的原因是:
        解释一:所谓虚函数就是多态情况下只执行一个,而从继承的概念来讲,总是要先构造父类对象,然后才能是子类对象,如果构造函数设为虚函数,那么当你在构造父类的构造函数时就不得不显示的调用构造,还有一个原因就是为了防错,试想如果你在子类中一不小心重写了个跟父类构造函数一样的函数,那么你的父类的构造函数将被覆盖,也即不能完成父类的构造.就会出错.

        解释二:虚函数的主要意义在于被派生类继承从而产生多态.   派生类的构造函数中,   编译器会加入构造基类的代码,   如果基类的构造函数用到参数,   则派生类在其构造函数的初始化列表中必须为基类给出参数,   就是这个原因.

 

最近有人问构造函数能不能是虚函数: 当然不能 解释一下: 1,从存储空间角度 虚函数对应一个vtable,这大家都知道,可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。 2,从使用角度 虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。 =: 虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。 三. 构造函数不需要是虚函数,也不允许是虚函数,因为创建一个对象时我们总是要明确指定对象的类型,尽管我们可能通过实验室的基类的指针或引用去访问它 但析构却不一定,我们往往通过基类的指针来销毁对象。这时候如果析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数。四: 从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数 从实际含义上看,在调用构造函数时还不能确定对象的真实类型(因为子类会调父类的构造函数);而且构造函数的作用是提供初始化,在对象生命期只执行一次,不是对象的动态行为,也没有太大的必要成为虚函数 五: 当一个构造函数被调用时,它做的首要的事情之一是初始化它的V P T R。因此,它只能知道它是“当前”类的,而完全忽视这个对象后面是否还有继承者。 当编译器为这个构造函数产生代码时,它是为这个类的构造函数产生代码- -既不是为基类,也不是为它的派生类(因为类不知道谁继承它)。 所以它使用的V P T R必须是对于这个类的V TA B L E。而且,只要它是最后的构造函数调用,那么在这个对象的生命期内, V P T R将 保持被初始化为指向这个V TA B L E。但如果接着还有一个更晚派生的构造函数被调用,这个构造函数又将设置V P T R指向它的 V TA B L E,等.直到最后的构造函数结束。V P T R的状态是由被最后调用的构造函数确定的。这就是为什么构造函数调用是从基类到更加派生 类顺序的另一个理由。 但是,当这一系列构造函数调用正发生时,每个构造函数都已经设置V P T R指向它自己的 V TA B L E。如果函数调用使用虚机制,它将只产生通过它自己的V TA B L E的调用,而不是最后的V TA B L E(所有构造函数被 调用后才会有最后的V TA B L E)。
析构函数设为虚函数的作用:    
        解释:在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。

 #include   "stdafx.h"  
   
 #include   "stdio.h"  
   
  class   A      
  {  
  public:  
   
  A();  
  virtual   ~A();  
   
  };  
  A::A()  
  {  
   
  }  
   
  A::~A()  
  {  
   
  printf("Delete   class   AP/n");  
   
  }  
  class   B   :   public   A      
  {  
  public:  
  B();  
          ~B();  
   
  };  
   
  B::B()  
  {  
   
  }  
   
  B::~B()  
  {  
  printf("Delete   class   BP/n");  
  }  
  int   main(int   argc,   char*   argv[])  
  {  
  A   *b=new   B;  
  delete   b;  
            return   0;  
   
  }      
   
  输出结果为:Delete   class   B        
                          Delete   class   A  
   
  如果把A   的virtual   去掉:  
                        那就变成了Delete   class   A

 

原创粉丝点击