编程笔记(3)

转载请标明出处:blog.csdn.net/zhangxingping

关于虚的析构函数

    析构函数是一种比较特殊的成员函数。它的作用与构造函数相反,是当对象脱离其作用域或者被销毁(delete)的时候隐式地被调用的一种函数。通常在析构函数中需要完成的是诸如释放对象申请的内存空间,关闭对象使用的文件等善后工作。析构函数的名称为类名称前面加上~,并且析构函数是不需要参数也没有返回值的。在继承关系中,当销毁一个派生类的对象的时候,会先调用派生类的析构函数,然后调用其基类的构造函数,以便完成派生类对象的彻底销毁。

    在C++中还有一个概念就是虚函数,虚函数是为了实现多态性而引入的,其目的是实现动态编联。虚函数可以被派生类重新定义。当使用基类指针指向派生类对象的时候,对虚函数的调用实际上是会根据指针指向对象的实际类型而调用对应类中的函数。

    把析构函数和虚函数的概念结合起来就会出现一个问题:哪些类的构造函数应该被声明为是virtual的呢? 哪些类有不需要把其构造函数声明为virtual的呢?

    先来看看下面的两段程序输出结果有什么不同。

程序1:

#include <iostream>
 
using namespace std;
 
class Base
{
public:
    Base()
    {
 
    }
    ~Base()
    {
        cout << "Base" << endl;
    }
};
 
class Sub:public Base
{
public:
    Sub()
    {
 
    }
    ~Sub()
    {
        cout << "Sub" << endl;
    }
 
};
 
 
int main()
{
    Base * p = new Sub();
    delete p;
}


上面程序的输出如下:

Base

程序2:

#include <iostream>
using namespace std;
class Base
{
public:
    Base()
    {
    }
    virtual ~Base()
    {
        cout << "Base" << endl;
    }
};
class Sub:public Base
{
public:
    Sub()
    {
    }
    ~Sub()
    {
        cout << "Sub" << endl;
    }
};

int main()
{
    Base * p = new Sub();
    delete p;
}

       这个程序则会输出:

Sub

Base

    这两个程序的差别就在于Base的析构函数是否为virtual的只有在Base的析构函数为virtual的时候,如果我们使用基类指针指向派生类对象,那么当该派生类对象被销毁的时候才能先调用派生类的析构函数,再调用基类的析构函数。

       从上面的示例程序中似乎不能看出这点的重要性。结合实际中析构函数通常完成的功能为释放对象申请的空间,关闭对象使用的文件等结合起来,问题就会变得很严重了。如果在使用时没有达到正确调用派生类析构函数,再调用基类析构函数的目的的话,就会出现内存的泄露,资源等得不到释放等严重问题。这个问题也是笔者在工作中遇到过的问题:在图像处理程序中通常需要申请的内存空间量较大;由于没有把基类的析构函数声明为virtual的,导致系统内存很快耗尽,进而程序崩溃。

       深究这个问题的根本原因实质上还是virtual 关键字的本质的问题。只不过这个本质结合析构函数带来的问题会更隐蔽。从上面的示例程序可见,一般情况下一个类的析构函数都应该被声明为时virtual的(VC中通过向导创建的类,析构函数缺省都是virtual的);除非你能十分肯定该类不会被继承或者该类不会被结合多态性来一起使用。

       具体的关于哪些情况下,我们应该把类的析构函数声明为virtual的,那些情况下不需要请参见:http://www.cppblog.com/aaxron/archive/2010/12/23/137293.html

       正如上面博文中描述的那样:实际编程中,前文描述的那个“除非”是我们都很难保证的,特别是当我们编写的程序是类似API或者SDK等基础类的时候,这样的类通常都是提供给别的人员使用的。我们无法保证别人不采用多态性的机制。因此建议所有类的析构函数都应该被设计为virtual的。有人可能认为在确实不需要多态性机制的情况下,把类的析构函数声明为virtual相比之下会增加程序运行的开销。但是这个开销实际上是很少的。这也是为什么诸如Objectiv-c中的类都具有多态性的原因了。

规则7: 一般情况下一个类的析构函数都应该被声明为是virtual的,除非你能十分肯定该类不会被继承或者该类不会被结合多态性来一起使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值