在子类继承父类的时候,关于父类中的析构函数为什么得设置成为虚函数问题,一直困扰着我。在查阅了C++ primary 5 P552 后,大致对虚析构函数有了一定了解,在这里和大家分享一下。
其实主要原因是为了避免内存泄露,因为在继承关系中,允许父类的指针或者引用指向子类的对象。比如
class A{
public:
//其他函数的定义
vitual void mark();
private:
//。。。。。
}
class B::public A{
public:
//其他函数定义
void mark() override;
private:
//。。。。
}
上面A为基类,B public继承自A,那么
B b;
A *p=&b;
是完全成立的,并且在函数调用基类指针或者引用作为形参,在调用虚函数的时候,会发生动态绑定,因为基类的指针或者引用可以指向自身类对象,也可以指向子类的对象。
好了,下面进入正题,分析为什么虚析构函数会避免内存泄露问题。
同样引用上述代码,只加上析构函数,假定其析构函数不是虚函数,代码如下:
class A{
public:
//其他函数的定义
vitual void mark();
~A()=default;
private:
//。。。。。
}
class B::public A{
public:
//其他函数定义
void mark() override;
~B()=default;
private:
//。。。。
}
B b;
A *p=&b;
delete p;
此时程序是使用积累的额指针指向派生类的对象,当delete时,本意是删除派生类对象。但是因为此时析构函数并不是虚函数,故不会发生动态绑定,
进行删去派生类对象的动作。程序会产生未定义行为,派生类对象也没有删除。
如果将析构函数设置为虚函数,代码如下:
class A{
public:
//其他函数的定义
vitual void mark();
virtual ~A()=default;
private:
//。。。。。
}
class B::public A{
public:
//其他函数定义
void mark() override;
~B()=default;
private:
//。。。。
}
B b;
A *p=&b;
delete p;
此时因为基类的析构函数是虚函数,当delete p时,会发生动态绑定派生类的析构函数,从而删除派生类对象,避免了内存泄露问题。