版权声明:转载请注明出处,谢谢!!! https://blog.csdn.net/qhdhnbd110/article/details/83105971
1. 避免内存泄漏
首先,我们实现一个多态:
class CPeople
{
public:
CPeople(){}
virtual ~CPeople(){}
};
class CChinese:public CPeople
{
public:
CChinese(){...}
~CChinese(){...}
}
class CAmerican:public CPeople
{
public:
CAmerican(){...}
~CAmerican(){...}
}
class CJapanese:public CPeople
{
public:
CJapanese(){...}
~CJapanese(){...}
}
这样我们就可以用一个基类指针指向不同国家的人:
CPeople *pSomePeopleA = new CChinese;
CPeople *pSomePeopleB = new CJapanese;
CPeople *pSomePeopleC = new CAmerican;
然而,当我们delete掉基类指针时,就会出现内存泄漏的问题:
delete pSomePeopleA;
delete pSomePeopleB;
delete pSomePeopleC;
这是因为delete操作仅仅删除了子类中基类的部分,而子类的部分并没有释放掉。
产生的原因是因为基类的析构函数是一个non-virtual析构。
这里先说一下析构函数的运作方式:
如果一个子类对象的生命周期结束,那么子类对象中的析构函数会调用其父类对象的析构函数,也就是从底往上依次调用析构,但不会出现自上而下调用析构,也就是说,如果删除了一个具有non-virtual的父类对象,那么它不会继续向下调用析构,所以子类部分并没有被删除。
解决的方法显而易见,将父类的non-virtual析构改为virtual析构函数:
class CPeople
{
public:
CPeople(){}
virtual ~CPeople(){}
};
这样,编译器就会从父类开始向下直到找到一个具有non-virtual析构函数的子类对象,然后再自底向上调用析构,这样就可以避免内存泄漏。
2. 何时应该添加virtual析构
如果基类被设计的目的是为了实现多态,即class中至少有一个虚函数,那么我们就要为这个基类添加虚析构。
3. 抽象类
一般而言,我们用普通类就可以实现多态,但是为什么还要用抽象类呢?
如果你看到一个抽象类,那么你可以确定它就是用来实现多态的,你会更加关注它子类的情况;
如果你看到一个普通的基类,你不确定它会不会被用来实现多态,会不会在某个地方被实例化。
简而言之,不容易让人产生迷惑。
抽象类实现方法:类中成员函数只要有一个是纯虚函数,那么这个类就会成为一个抽象类。