`
eriol
  • 浏览: 401087 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

析构函数与virtual

    博客分类:
  • C++
阅读更多

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

 

#include <iostream.h>

struct A
{
    virtual ~A() {cout<<"~A()\n";}
};

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

void main()
{
    A* p = new B;
    delete p;
}

 

    如果 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也无妨。

 

 

为什么内联函数,构造函数,静态成员函数不能为virtual函数?

 

(1) 内联函数

 

内联函数是在编译时期展开,而虚函数的特性是运行时才动态联编,所以两者矛盾,不能定义内联函数为虚函数。

 

(2) 构造函数

 

构造函数用来创建一个新的对象,而虚函数的运行是建立在对象的基础上。在构造函数执行时,对象尚未形成,所以不能将构造函数定义为虚函数。

 

(3) 静态成员函数

 

静态成员函数属于一个类而非某一对象,没有this指针,它无法进行对象的判别。

分享到:
评论

相关推荐

    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++虚析构函数的使用分析

    析构函数的功能是在该类对象消亡之前进行一些必要的清理工作,析构函数最好都是virtual的。首先解释一下虚构函数和指针之间是如何交互的,以及虚析构函数的具体含义。例如以下代码,其中SomeClass是含有非virtual析...

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

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

    C++多态性实验报告

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

    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++笔试题全部汇总

    3. 父类的析构函数是非虚的,但是子类的析构函数是虚的,delete子类指针(指向该子类对象)[特殊情况,参见题5],会调用父类的析构函数(正确)//任何情况下删除子类都会调用到父类的析构函数 4.对于下面的类CA,...

    第七次实验报告1

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

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

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

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

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

    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函数。

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

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

    QT资源文件111

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

    C++接口定义及实现举例

    一、接口的定义  有时候,我们得提供一些接口给别人使用。接口的作用,是提供一个与其他...//注意,好要定义此虚析构函数,能够避免其实现不能正常调用析构函数的问题 //提供给外面使用的接口一般采用纯虚函数 vi

Global site tag (gtag.js) - Google Analytics