析构函数为虚函数

析构函数执行时先调用派生类的析构函数,其次才调用基类的析构函数。如果析构函数不是虚函数,而程序执行时又要通过基类的指针去销毁派生类的动态对象,那么用delete销毁对象时,只调用了基类的析构函数,未调用派生类的析构函数。这样会造成销毁对象不完全。

#include<iostream.h>
#include<stdlib.h>

class CPerson
{
public:
    virtual ~CPerson();       //基类的析构函数必须声明为虚函数,否则

                                用delete销毁对象时会出错
protected:
 char * m_lpszName;
 char * m_lpszSex;
};

class CStudent:public CPerson
{
public:
 ~CStudent();              //virtual可加也可不加
protected:
 int m_iNumjber;           //学号
};

CPerson::~CPerson()
{
 cout<<"~CPerson!"<<endl;
}


CStudent::~CStudent()
{
 cout<<"~CStudent!"<<endl;
}

void main()
{
 CPerson * poCPerson = new CStudent;        //构造一个CStudent的动态对象
 if(NULL==poCPerson)
 {
  exit(0);
 }
 delete poCPerson;
 cout<<"CStudent对象已经完成析构"<<endl;     //如果析构函数是非虚函数,

                                               那么CStudent对象就未析构完
 CStudent oCStudent;
}

 

输出:

~Student!

~CPerson!

CStudent对象已经完成析构

~Student!

~CPerson!

 

如果去掉~CPerson()前面的virtual,且将“CStudent对象已经完成析构”改为“CStudent对象未完成析构”。程序的执行结果为:

~CPerson!

CStudent对象未完成析构

~Student!

~CPerson!


参考:http://359611946.blog.163.com/blog/static/1161900200976115331797/

<think>好的,用户想了解C++中虚析构函数的作用和必要性。我之前学过一些相关知识,但得仔细回忆一下。根据提供的引用内容,首先需要理解析构函数在继承体系中的调用机制。 记得引用3提到,如果基类的析构函数不是虚函数,当用基类指针指向派生类对象并删除该指针时,只会调用基类的析构函数,而派生类的析构函数不会被调用。这会导致派生类中分配的资源无法释放,造成内存泄漏。比如,用户可能有一个基类Base和一个派生类Derived,Derived的析构函数负责释放某些内存,如果析构函数不是虚的,那么删除基类指针时,Derived的析构函数不会被调用,导致内存泄漏。 引用2中也强调了这一点,说明如果基类析构函数不是虚的,派生类的析构函数不会执行,导致资源泄漏。这种情况下,将基类的析构函数声明为虚函数可以确保在删除基类指针时,正确调用派生类的析构函数,进而调用基类的析构函数。引用4提到,派生类析构函数执行完后会自动调用基类的析构函数,这个过程是隐式的。 但是,不是所有情况都需要虚析构函数。引用2指出,只有当类作为基类时,才需要将析构函数设为虚函数。因为虚函数会增加类的存储空间,每个对象需要维护一个虚函数表指针,这可能影响性能。所以,如果类不会被继承,或者不需要多态删除,就不必使用虚析构函数。 总结来说,虚析构函数的作用是确保通过基类指针删除派生类对象时,能够正确调用派生类和基类的析构函数,防止资源泄漏。必要性在于处理多态场景下的对象销毁,避免内存泄漏。而使用时需权衡,仅在基类中需要时才声明虚析构函数,避免不必要的开销。 接下来需要组织这些点,用用户提供的引用作为支持,并生成相关问题。</think>### C++虚析构函数的作用与必要性 #### 作用说明 1. **确保派生类资源释放** 当通过**基类指针删除派生类对象**时,若基类析构函数未声明为虚函数,编译器会仅调用基类的析构函数,导致派生类资源泄漏[^2][^3]。例如: ```cpp Base* obj = new Derived(); delete obj; // 若基类析构非虚,仅调用Base::~Base() ``` 若将基类析构函数声明为虚函数(`virtual ~Base()`),则会触发动态绑定,正确调用派生类析构函数,再隐式调用基类析构函数[^1][^4]。 2. **支持多态对象销毁** 虚析构函数是**多态特性在对象销毁阶段的体现**,确保通过基类接口操作派生类对象时,销毁过程能完整覆盖所有层级[^3]。 #### 必要性分析 1. **基类设计的关键约束** 若类需要作为基类且可能通过基类指针删除派生类对象,则必须声明虚析构函数。否则会导致: - 派生类析构函数未调用 → 资源泄漏 - 基类析构函数未调用 → 基类资源泄漏(但引用4指出,派生类析构函数会隐式调用基类析构函数,此处可能存在矛盾,需进一步确认) 2. **性能与存储权衡** 虚析构函数会引入虚函数表(vtable),增加对象存储开销(通常每个对象多一个指针大小)。因此: - 仅当类需要作为基类时声明虚析构函数 - 非基类或不会被多态使用的类无需虚析构函数 #### 代码示例 ```cpp // 正确实现 class Base { public: virtual ~Base() {} // 虚析构函数 }; class Derived : public Base { public: ~Derived() override { // 释放派生类资源 } }; // 使用场景 Base* obj = new Derived(); delete obj; // 调用Derived::~Derived() → Base::~Base() ``` #### 典型错误案例 ```cpp class Base { public: ~Base() {} // 非虚析构函数 }; class Derived : public Base { public: int* allocated_memory; Derived() { allocated_memory = new int[100]; } ~Derived() { delete[] allocated_memory; } // 不会被调用! }; Base* obj = new Derived(); delete obj; // 仅调用Base::~Base() → 内存泄漏 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值