构造函数、析构函数为虚函数的区别

关于C++类析构函数为虚函数时,如果是父类的指针用子类来new,如果发生析构时,析构函数是virtual与不是virtual有什么区别。


一、先看第一种最简单的情况吧,教科书上教的,析构函数不是virtual,正常定义一个子类对象

class student   
{   
public:   
    int *m_pInt;   
    student()   
    {   
        m_pInt = new int[10];   //1   
        memset(m_pInt, 0, 10*4);   
    }   
   
    ~student()   
    {               //3   
        delete []m_pInt;   
    }   
   
};   
   
class GradeOneStue:public student   
{   
public:   
    int m_iNum;   
    GradeOneStue()             
    {               //2   
        m_iNum = 1;   
    }   
   
    ~GradeOneStue()   
    {               //4   
        m_iNum = 0;   
    }   
};   
   
int _tmain(int argc, _TCHAR* argv[])   
{   
    GradeOneStue gd;   
    return 0;   
}  

构造函数:先调用父类构造函数,再调用子类构造函数;

再来看看析构时的顺序(教科书上写的是先调用子类的析构函数,在调用父类的,与构造过程相反)  


二、析构函数是virtual,正常定义一个子类对象

析构函数最后还是调用了父类的析构(即使是虚函数)。


三、用一个父类指针去new一个子类对象,析构函数不是virtual,构造过程略过

看到只调用了父类的析构函数,此时子类的析构函数没有被调用,此时子类的析构函数中虽然有调用父类析构函数的代码,但是这里直接调用的是父类的析构函数,所以这是如果子类中析构函数有释放资源的代码,这里会造成这部分资源不被释放,有可能造成内存泄


四、用一个父类指针去new一个子类对象,析构函数是virtual,构造过程略过

由于子类的虚构函数最后会调用父类的析构函数(不管是否为virtual,子类析构函数最后都会调用父类析构函数),所以最终父类的析构函数会得到执行。(这时调用的析构函数相当于pStu->vpTable->析构函数(),这个析构函数是构造时写入的,由于构造时使用子类类型去new,此时虚函数表中析构函数的地址是子类的析构函数地址


最后的结论:

1、无论父类与子类的析构函数是否是virtual,子类的析构函数都会调用父类的析构函数

2、如果父类与子类的析构函数不为virtual,用一个父类指针指向一个用子类类型new的对象,delete时,直接调用父类的析构函数,这是在编译时刻就决定的。如果子类析构函数中有释放资源的代码,这是会发生资源泄漏。

3、如果父类与子类的析构函数是virtual,用一个父类指针指向一个用子类类型new的对象,delete时,这时由于是通过虚函数表调用析构函数,而虚函数表中的地址是构造时写入的,是子类的析构函数的地址,由于结论第一条,所以子类与父类的析构函数都会得到调用,不会发生资源泄漏。



*************************************************************************************************************

补充:为什么构造函数不能用虚函数

如果有这样两个类:
class A {
public:
  A() { a = "A"; f(); }
  virtual ~A() {}

  virtual f() { cout << a << endl; }
private:
  char* a;
};
class B : public A {
public:
  B() { b = "B"; }
  ~B() {}

  f() { cout << b << endl; }
private:
  char* b;
};

构造函数调用顺序是先调用基类构造函数,即: A(), B()
在A()中调用f(),如果按虚函数调用规则,它应该调用B::f(),但此时B还没构造(B()还没有执行),执行B::f()必然是一个错误。所以在构造函数内部执行时,对象还没有完全构造好,不能按虚函数方式进行调用,构造函数本身不能为虚函数也是相同的原因了。




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值