您的位置:首页 > 其它

多态基类的析构函数必须加上virtual

2014-03-19 17:13 323 查看
《Effective C++》说:

        因为C++明确指出,当derived class对象经由一个base class指针被删除,而base class带着一个non-virtual析构函数,其结果未有定义---实际执行时通常发生的是对象的derived成分没被销毁。如:baseclass *ptb = derivedclassFuc() //子类的一个函数; 其中baseclass中有个non-virtual析构函数。解决这一问题的方法就是把基类中的析构函数声明为virtual,通常还有其他virtual函数。任何class只要还有virtual函数都几乎确定应该也有一个virtual析构函数。                                     

       如果class不含virtual函数,通常表示它并不意图被用做一个base class.当class不企图被当作base class,令其析构函数为virtual往往是个馊主意。许多人的心得是:只有当class内含至少一个virtual函数,才为它声明virtual析构函数。

有时候令Class带一个pure virtual析构函数,可能颇为便利,纯虚函数导致抽象类,也就是不能被实体化的类,你不能为这种类型创建对象。所以为你希望它成为抽象的那个类声明一个pure virtual析构函数,这样你就不需要担心析构函数的问题了,不过你必须为这个pure virtual析构函数提供一份定义:如,AWOV::~AWOV ( ) { …….},析构函数的运作方式是,最深层派生的那个class其析构函数最先被调用,然后是其每一个base class的析构函数被调用。编译器会在AWOV的derived
classes的析构函数中创建一个对~AWOV的调用动作,所以你必须为这个函数提供一份定义,否则,连接器会出问题。

=======================================

把析构函数定义成虚函数,可以有效的防止在之后继承的时候,子类指针的内存泄露.

比如,

class A

class B:public A

A *ptr=new B

在这种情况下调用析构函数的时候,就会发生删除了A的空间而没有删除B的空间,

所以将基类定义为抽象类,可以让其子类动态的去调用它自身的函数。

========================================

class Base

{

public:

    Base(){}

    virtual void VirFun()

    {

    }

     ~Base(){}    //实际上这里必须加virtual 

private:

    //Some attribute

};

class Sub : public Base

{

public:

    Sub(){}

    virtual void VirFun()

    {

    }

    ~Sub(){}

private:

    //Some attribute

};

上面的例子是个简单的多态。

在我们应用的时候,我们经常会这么干:

Base * pBase = new Sub();//new了一个Sub对象,它实际上包含了Base 的子对象。

pBase->VirFun(); //很好,它会根据实际的类型调用Sub 的 VirFun()

delete pBase;//完蛋了,它调用了Base的析构。Sub的析构?这可不关我事,我可是Base类型的。

于是内存泄漏了。。。

给Base的析构函数加上virtual之后呢?

delete pBase; //很好,它继续多态调用实际类型对象的析构。

大家知道,子类的析构函数会自动调用父类的析构。

于是,啊哈,终于安全了。

至此,大家应该对题目的意思有了大概的了解了。

有没有发现,virtual 析构函数挺有意思的,它的子类析构函数名字和父类不同,一样会重写父类的析构函数。

为什么题目要强调“多态 基类”呢?

class Base

{

public:

    Base(){}

    void Fun()

    {

    }

   

    virtual ~Base(){}

private:

    //Some attribute

};

class Sub : public Base

{

public:

    Sub(){}

    void Fun()

    {

    }

    ~Sub(){}

private:

    //Some attribute

};

这样的继承中,有没有必要给父类析构函数加virtual呢?

从语法意义上来说,是应该的,因为你像下面这样写的时候,语法是没有错误的:

Base * pBase = new Sub();//new了一个Sub对象,它实际上包含了Base 的子对象。

delete pBase; //很好啊,程序多安全啊。有什么问题吗?

在这样写的时候,你应该谴责自己。

pBase的所有行为都是Base中定义的,为什么要给它一个Sub的身体呢?

(为什么网上很多男士都爱用美女作头像呢。。。)

所以,当你设计的类系不具备多态性的时候,请不要:

1.用父类的指针指向子类;

2.给父类的析构函数加上virtual(毕竟虚函数表也是不小的开销不是?)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: