`

析构函数virtual与非virtual区别

 
阅读更多

作为通常的原则,如果一个类定义了虚函数,那么它的析构函数就应当是virtual的。因为定义了虚函数则隐含着:这个类会被继承,并且会通过基类的指针指向子类对象,从而得到多态性。   这个类可能会被继承,并且会通过基类的指针指向子类对象”,因此基类的析构函数是否为虚将决定子类的对象是否被析构。

 

很多时候你只能够获取基类指针,但却不知道它实际是哪个子类,这时候删除基类指针时虚析构函数就很有用了。
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include <iostream>
using namespace std;
struct A
{
    A(){cout 
<< "A::()"<<endl;}
    
virtual ~A() {cout<<"~A()\n";}
};

struct B: public A
{
    B(){cout 
<< "B::()"<<endl;}
    
~B() {cout<<"~B()\n";}
};

int main()
{
    A
* p = new B;
    delete p;
    
//B b;
    return 0;
}


如果 A的析构函数不是virtual的,那么此时就不是先调用B的析构函数再调用A的析构函数。
输出:
~A(); 

如果A   的析构函数为virtual,则先~B(),再~A()  
输出:
~B();
~A();

类如果会被派生的话,析构函数一般都应该定义为virtual的,主要不是防止内存泄露,而是为了正确的析构。如果是个封闭类(即不再被派生),就不要定义为virtual的。虚函数毕竟耗费较大的。

不用virtual 的几种情况:
  1、作为非公有基类。仅作为   private   base   class   使用的   class   不需要使用虚拟析构函数  
  2、不作为接口使用的基类。  
  3.   如果你可以保证这个类不被public继承(private/protected继承的话,在非friend函数/类中就无法用基类指针指向派生类了)  
  4.   如果它的所有派生类(包括派生类的派生类)的析构函数都是trivial的(这里的trivial指的是在程序员的层次什么事也不做)  
  5.   如果不需要用基类的指针指向派生类的对象  
  在这五种情况下,不把析构函数声明为virtual都是可以的,何况效率会高一些——但前提是你得保证前提的成立——不过这些保证常常是很难100%的:谁能保证别人在派生你的类的时候,析构函数是trivial的,或者别人不用你提供的基类的指针指向派生类对象?这些常常是很难得到保证的。  

声明基类的析构函数为virtual并非总是为了防止memory   leak   另外这也只是作为一般的原则(基类中有虚函数则把其析构函数声明为virtual)。如果你的析构函数什么事也不作,从效果上来说,不声明为virtual也无妨
转自:http://www.cppblog.com/aaxron/archive/2010/12/23/137293.html

<script type="text/javascript"></script>
分享到:
评论

相关推荐

    C++析构函数使用virtual的原因

    C++析构函数使用virtual的原因

    C++中基类的析构函数为什么要用virtual虚析构函数.pdf

    C++中基类的析构函数为什么要用virtual虚析构函数.pdf

    c++虚析构函数及虚函数的详细例子.rar

    c++ virtual 虚析构函数及虚函数的详细例子.rar

    C++虚基类 虚函数 虚析构函数

    //析构函数做成员函数 }; Base::~Base()//成员函数实现 { cout; } class Derived:public Base { public: Derived(); ~Derived(); private: int *p; }; Derived::Derived() { p=new int(0);//从堆上分配一个int型...

    C++中确定基类有虚析构函数

    本文给大家介绍了C++中确定基类有虚析构函数的方法。

    C++虚析构函数的使用分析

    在C++中,不能声明虚构造函数,但可以声明虚析构函数。...例如以下代码,其中SomeClass是含有非virtual析构函数的一个类:SomeClass *p= new SomeClass;. . . . . .delect p;为p调用delect时,会自动调用SomeClass

    详解C++中虚析构函数的作用及其原理分析

    C++中的虚析构函数到底什么时候有用的,什么作用呢。 一.虚析构函数的作用 总的来说虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的。也就说虚析构函数使得在删除指向子类对象的基类...

    C++开发培训资料

    当通过父类指针delete一个子类对象时,构造的行为未定义 在父类的析构函数前加virual,使用之成为虚析构函数 父类的析构函数在子类的析构函数执行...如果一个类中有virtual函数,那么该类就应该提供一个virual析构函数。

    虚函数被类的构造析构函数和成员函数调用虚函数的执行过程

    代码如下:#include class base{public:  base() { std::cout&lt;&lt;std::endl;... virtual ~base() { std::cout&lt;&lt;std::endl; std::cout&lt;&lt;“base distructor”&lt;&lt;std::endl; func

    C++多态性实验报告

    ○2先不将析构函数声明为virtual,在main函数中另设一个指向Circle类对象的指针变量,使它指向变量,使它指向grad1。运行程序,分析结果。 ○3不作第②点的修改而将析构函数声明为virtual,运行程序,分析结果。 (2...

    网络编程-多点聊天-源码

    //消息类的定义 class CMsg : public CObject ... //析构函数 virtual void Serialize(CArchive& ar); //序列化函数 //Attributes public: CString m_strBuf; //字符串成员 BOOL m_bClose; //是否关闭状态

    华为C++笔试题全部汇总

    delete p[由于p被声明成父类指针,并且父类和子类的析构函数都非虚,因此delete操作只能根据p指针声明的类型来调用父类的析构函数]; std::cout ; } 6.请问下面这段程序的输出结果是_A_: A. 2,1, B. 2,2, C. 1,1,...

    网狐6.6 服务器源代码 & 共享组件 & 数据库 (2)

    //析构函数 virtual ~CSkinResource(); //基础接口 public: //释放对象 virtual VOID __cdecl Release() { return; } //接口查询 virtual VOID * __cdecl QueryInterface(REFGUID Guid, DWORD dwQueryVer); ...

    C++ 课程作业 第六章 数组指针与字符串2——vector类(图书管理)

    3、设计构造与析构函数,不要求输出信息,但各位同学可以自己输出并分析各个对象的创建与删除的情况: Book();//将m_ID初始化为0,表示这个一个未赋值对象 virtual ~Book();//无具体的工作 Book(const Book& other...

    QT资源444444

    应用程序的plugin实际是实现了一个或多个接口(interface)的动态库。应用程序与plugin之间的... 一个接口(interface)通常声明一个virtual析构函数,一个返回QStringList的virtual函数,以及一个或多个其他virtual函数。

    QT文件1111

    应用程序的plugin实际是实现了一个或多个接口(interface)的动态库。应用程序与plugin之间的... 一个接口(interface)通常声明一个virtual析构函数,一个返回QStringList的virtual函数,以及一个或多个其他virtual函数。

    QT文件222222

    应用程序的plugin实际是实现了一个或多个接口(interface)的动态库。应用程序与plugin之间的... 一个接口(interface)通常声明一个virtual析构函数,一个返回QStringList的virtual函数,以及一个或多个其他virtual函数。

    QT资源文件111

    应用程序的plugin实际是实现了一个或多个接口(interface)的动态库。应用程序与plugin之间的... 一个接口(interface)通常声明一个virtual析构函数,一个返回QStringList的virtual函数,以及一个或多个其他virtual函数。

    超级报表Super Report V3.5(附VC++6.0编译的Bin)

    //析构函数 virtual ~CViewReport(); //自定义报表 void DefineReport(); //增加记录, //如:AddRecord("字段一|字段二|%s|",strVal); //以下阐述仅适用于ReportMode=0模式: //第一次调用AddRecord(..)时...

    第七次实验报告1

    (2) 当析构函数设置为virtual时(一般只需在顶级父类中声明即可),其调用的将会是真实对象的destructor,然后系统一级级地撤销父类的资源 (3)

Global site tag (gtag.js) - Google Analytics