effective c++条款07:为多态基类声明virtual析构函数

版权声明:转载请注明出处,谢谢!!! 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. 抽象类

一般而言,我们用普通类就可以实现多态,但是为什么还要用抽象类呢?

如果你看到一个抽象类,那么你可以确定它就是用来实现多态的,你会更加关注它子类的情况;

如果你看到一个普通的基类,你不确定它会不会被用来实现多态,会不会在某个地方被实例化。

简而言之,不容易让人产生迷惑。

抽象类实现方法:类中成员函数只要有一个是纯虚函数,那么这个类就会成为一个抽象类。

猜你喜欢

转载自blog.csdn.net/qhdhnbd110/article/details/83105971