精华内容
下载资源
问答
  • C++中将析构函数定义为虚函数
    2019-05-04 22:08:24

    C++中为什么在共有继承时,要将基类的对象定义成员虚函数,就是因为:在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员.如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数.。有因为析构函数不能被继承到派生类,所以要定义为虚函数。
    可以看看这个博主写的:
    http://blog.sina.com.cn/s/blog_7c773cc50100y9hz.html

    1.第一段代码
    

    #include
    using namespace std;
    class ClxBase{
    public:
    ClxBase() {};
    ~ClxBase() {cout << “Output from the destructor of class ClxBase!” << endl;};
    void DoSomething() { cout << “Do something in class ClxBase!” << endl; };
    };
    class ClxDerived : public ClxBase{
    public:
    ClxDerived() {};
    ~ClxDerived() { cout << “Output from the destructor of class ClxDerived!” << endl; };
    void DoSomething() { cout << “Do something in class ClxDerived!” << endl; };
    };
    int main(){
    ClxDerived *p = new ClxDerived;
    p->DoSomething();
    delete p;
    return 0;
    }
    运行结果:
    Do something in class ClxDerived!
    Output from the destructor of class ClxDerived!
    Output from the destructor of class ClxBase!
    这段代码中基类的析构函数不是虚函数,在main函数中用继承类的指针去操作继承类的成员,释放指针P的过程是:先释放继承类的资源,再释放基类资源.

    2.第二段代码
    #include
    using namespace std;
    class ClxBase{
    public:
    ClxBase() {};
    ~ClxBase() {cout << “Output from the destructor of class ClxBase!” << endl;};
    void DoSomething() { cout << “Do something in class ClxBase!” << endl; };
    };
    class ClxDerived : public ClxBase{
    public:
    ClxDerived() {};
    ~ClxDerived() { cout << “Output from the destructor of class ClxDerived!” << endl; };
    void DoSomething() { cout << “Do something in class ClxDerived!” << endl; }
    };
    int main(){
    ClxBase *p = new ClxDerived;
    p->DoSomething();
    delete p;
    return 0;
    }
    输出结果:
    Do something in class ClxBase!
    Output from the destructor of class ClxBase!
    这段代码中基类的析构函数同样不是虚函数,不同的是在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了基类的资源,而没有调用继承类的析构函数.调用dosomething()函数执行的也是基类定义的函数.
    一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,造成内存泄漏.
    在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员.如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数.
    析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的.

    3.第三段代码:
    #include
    using namespace std;
    class ClxBase{
    public:
    ClxBase() {};
    virtual ~ClxBase() {cout << “Output from the destructor of class ClxBase!” << endl;};
    virtual void DoSomething() { cout << “Do something in class ClxBase!” << endl; };
    };
    class ClxDerived : public ClxBase{
    public:
    ClxDerived() {};
    ~ClxDerived() { cout << “Output from the destructor of class ClxDerived!” << endl; };
    void DoSomething() { cout << “Do something in class ClxDerived!” << endl; };
    };
    int main(){
    ClxBase *p = new ClxDerived;
    p->DoSomething();
    delete p;
    return 0;
    }
    运行结果:
    Do something in class ClxDerived!
    Output from the destructor of class ClxDerived!
    Output from the destructor of class ClxBase!
    这段代码中基类的析构函数被定义为虚函数,在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了继承类的资源,再调用基类的析构函数.调用dosomething()函数执行的也是继承类定义的函数.

    如果不需要基类对派生类及对象进行操作,则不能定义虚函数,因为这样会增加内存开销.当类里面有定义虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间.所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数.
    
    更多相关内容
  • C++析构函数定义和使用

    千次阅读 2021-06-10 20:22:40
    2.1 析构函数定义和使用 析构函数(destructor)是一个特殊的成员函数,它的作用与构造函数相反,它的名字是类名的前面加一个“~”符号。在C++中“~”是位“取反”运算符,从这一点可以想到:析构函数是与构造...

    析构函数

    2.1 析构函数定义和使用

           析构函数(destructor)是一个特殊的成员函数,它的作用与构造函数相反,它的名字是类名的前面加一个“~”符号。在C++中“~”是位“取反”运算符,从这一点可以想到:析构函数是与构造函数作用相反的函数。例如:

    class student{

    public:

        student()//构造函数

        {

        }

        ~student() //析构函数

        {   }

        void print(){}

    };

           可以看到,定义了一个student类。然后,定义student类的构造函数和析构函数。其中,析构函数的定义如下:

    ~student(){ }

           那么,函数名是类名前面添加取反符号“~”,而且,函数没有参数。

           当对象的生命周期结束的时候,就会自动执行析构函数。如果出现以下几种情况,程序就会执行析构函数:

    (1) 如果在一个函数中定义了一个对象,那么,该对象就是局部对象,当这个函数被调用结束时,对象的生命周期结束。此时,对象应该释放(销毁),在对象释放(销毁)前自动执行析构函数。

    (2) static 局部对象在函数调用结束时对象并不释放(销毁),因此,不调用析构函数,只在main() 函数结束或调用exit()函数结束程序的时候,才调用static局部对象的析构函数。

    因为static局部对象的生命周期是整个程序运行过程,所以,只有程序结束运行的时候,static局部对象的生命周期才结束,才执行类的析构函数。

    (3) 如果定义了一个全局对象,全局对象的生命周期是整个程序运行过程,所以,当程序结束运行的时候,全局对象才销毁,此时,调用该全局对象的析构函数。

    (4) 如果用new运算符动态地建立了一个对象,当用delete运算符释放该对象时,先调用该对象的析构函数。

           析构函数的作用并不是删除对象,而是在撤销对象占用的内存之前,完成一些清理工作。使这部分内存可以被程序分配给新对象使用。程序设计者要设计好析构函数,以完成所需的功能,只要对象的生命周期结束,程序就会自动执行析构函数来完成这些工作。

           析构函数不返回任何数值,也没有函数类型 和 函数参数。由于没有函数参数,因此,它不能被重载。一个类可以有多个构造函数,但是,只能有一个析构函数。

           一般情况下,类的设计者应当在声明类的同时定义析构函数,以指定如何完成“清理”的工作。如果用户没有定义析构函数,C++编译系统会自动生成一个 默认析构函数,但是,它只是有析构函数的名称和形式,实际上什么操作都不进行。想让析构函数完成任何工作,都必须在定义的析构函数中执行。

           如下是一个程序测试例子,讲解构造函数和析构函数的使用。

           程序运行结果如下:

           在main()函数中,定义一个if(1){}代码块,在代码块中定义stud局部变量。当退出代

    码块的时候,销毁stud局部变量,看到析构函数的调用。

           所以,我们看到对象销毁的时候,自动调用析构函数。析构函数是不可以手动调用的。是对象销毁的时候,由系统自动调用。

           所以,对象销毁的时候,我们想释放一些资源,就可以放在析构函数中操作。例如,student类中的name, addr是动态申请的内存。那么,在析构函数中就释放这些内存。

    韦凯峰 Linux C/C++ 程序设计教程,Linux 系统编程,Openwrt 系统开发,微信:13926572996,QQ:1523520001,博客:www.mylinux.vip

    展开全文
  • 析构函数定义为虚函数

    千次阅读 2019-07-06 12:12:46
    Q:析构函数为什么要定义为虚函数? 1.我们在之前的学习中都知道,在调用构造函数时先调用基类的构造函数,再调用派生类构造函数;而当调用析构函数时,则要先调用派生类的析构函数再调用基类的析构函数 #include<...

    Q:析构函数为什么要定义为虚函数?

    1.我们在之前的学习中都知道,在调用构造函数时先调用基类的构造函数,再调用派生类构造函数;而当调用析构函数时,则要先调用派生类的析构函数再调用基类的析构函数

    #include<iostream>
    using namespace std;
    class A{
    public:
    	A(){
    		cout << "A()" << endl;
    	}
    	~A()
    	{
    		cout << "~A()" << endl;
    	}
    };
    class B :public A{
    public:
    	B(){
    		cout << "B()" << endl;
    	}
    	~B(){
    		cout << "~B()" << endl;
    	}
    };
    int main()
    {
    	B *b=new B;       //构造一个B类对象
    	delete b;                   //释放内存,调用析构函数
    	return 0;
    }
    

    结果为:
    在这里插入图片描述

    • 由此我们可以证明构造函数的调用顺序以及析构函数的调用顺序
    • 还可以发现在delete b时,派生类和基类都调用析构函数完成了资源的清理工作

    2.当基类指针指向派生类对象时

    #include<iostream>
    using namespace std;
    class A{
    public:
    	A(){
    		cout << "A()" << endl;
    	}
    	~A()
    	{
    		cout << "~A()" << endl;
    	}
    };
    class B :public A{
    public:
    	B(){
    		cout << "B()" << endl;
    	}
    	~B(){
    		cout << "~B()" << endl;
    	}
    };
    int main()
    {
    	A *a=new B;
    	delete a;
    	return 0;
    }
    

    运行结果为:
    在这里插入图片描述

    • 我们发现在delete a时,只调用了基类的析构函数,没有调用派生类的析构函数,那么就会导致内存泄漏
    • 这是因为在调用普通函数时,在编译期间已经确定了它所要调用的函数(静态绑定),因为a是A*类型,因此只会调用基类的析构函数

    3.为了解决这一问题,我们建议将析构函数定义为虚函数

    #include<iostream>
    using namespace std;
    class A{
    public:
    	A(){
    		cout << "A()" << endl;
    	}
    	virtual ~A()
    	{
    		cout << "~A()" << endl;
    	}
    };
    class B :public A{
    public:
    	B(){
    		cout << "B()" << endl;
    	}
    	~B(){
    		cout << "~B()" << endl;
    	}
    };
    int main()
    {
    	B *b=new B;
    	A *a=(A*)b;
    	delete a;
    	return 0;
    }
    

    运行结果为:
    在这里插入图片描述

    • 我们发现delete a不仅调用了派生类析构函数也调用了基类构造函数
    • 这是因为当我们把基类析构函数定义为虚函数时,在调用析构函数时,会在程序运行期间根据指向的对象类型到它的虚函数表中找到对应的虚函数(动态绑定),此时找到的是派生类的析构函数,因此调用该析构函数;而调用派生类析构函数之后会再调用基类的析构函数,因此不会导致内存泄漏
    展开全文
  • 3、一个类中至多有一个析构函数,如果程序员没有定义析构函数,那么系统会自动地加入一个析构函数。 4、不能显式地调用析构函数,而是由系统自动调用。 定义析构函数格式为: ~类名() {…}  由于c#得到自动...
  • C++:什么情况下需要将析构函数定义为虚函数。
  • 在什么情况下把析构函数定义为私有的?-CSDN论坛-CSDN.NET-中国最大的IT技术社区 http://bbs.csdn.net/topics/80208934只能用new生成的对象 用new生成的对象,在面向对象中是很有用的.它保存在堆上,可以自由控制...
  • 析构函数的作用; 为类定义析构函数; 关于析构函数的几点说明; 复杂对象的构造函数和析构函数调用; 使用构造函数实现强制类型转换。
  • 很多情况下要求当前的程序中只有一个object。... 当我们在程序中声明一个对象时,编译器为调用构造函数(如果有的话),而这个调用将通常是外部的,也就是说它不属于class对象本身的调用,假如构造函数是私
  • 基类指针指向派生类,并且调用delete释放基类指针的空间时,如果不把基类的析构函数定义为虚函数,则只会调用基类的析构函数,而派生类部分没有调用析构函数,会造成内存泄露;下面程序的运行结构为: executing ...
  • C++中析构函数为虚函数

    万次阅读 多人点赞 2019-04-12 23:13:17
    (1)析构函数定义为虚函数时:基类指针可以指向派生类的对象(多态性),如果删除该指针delete []p;就会调用该指针指向的派生类析构函数,而派生类的析构函数又自动调用基类的析构函数,这样整个派生类的对象完全...
  • 不能在结构中定义析构函数。只能对类使用析构函数。 一个类只能有一个析构函数。 无法继承或重载析构函数。 无法调用析构函数。它们是被自动调用的。 析构函数既没有修饰符,也没有参数。 例如,下面是类 Car 的析构...
  • 析构函数定义

    万次阅读 多人点赞 2017-12-07 22:02:33
    1.析构函数定义 析构函数:当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统会自动执行析构函数析构函数往往用来做“清理善后”的工作(例如在建立对象时用new开辟了一段内存空间,则在该对象消亡...
  • C++中析构函数定义成虚函数的原因 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/SearchLife/archive/2009/03/12/3985341.aspx
  • 转载:https://www.cnblogs.com/kangyoung/articles/2375211.html ... 很多情况下要求当前的程序中只有一个object。例如一个程序只有一个和数据库的连接,只有一个鼠标的object。通常我们都将构造函数的声明置...
  • 析构函数__del__定义:在类里定义,如果不定义,Python 会在后台提供默认析构函数析构函数__del__调用: A、使用del 显式的调用析构函数删除对象时:del对象名;  class Foo: def __init__(self,x): self.x=x ...
  • 其实,析构函数是一个特殊的函数,编译器在编译时,析构函数的名字统一为destucter,所以只要父类的析构函数定义为虚函数,不管子类的析构函数前是否加virtual(可以理解为编译器优化),都构成重写。 再看刚才的...
  • 构造函数与析构函数

    2016-02-16 14:46:56
    其中,构造函数在定义对象时被调用,析构函数在对象释放时被调用。如果用户没有提供构造函数和析构函数,系统将提供默认的构造函数和析构函数。 1.构造函数 构造函数是一个与类同名的方法,可以没有参数,有一个参数...
  • 析构函数为什么虚函数,不是虚函数又能怎么样呢,我们先来看个例子 class A { public: A() {}; ~A() { cout << "destruct A" << endl; }; }; class B :public A { public: B() {}; virtual ~B...
  • a.h class A {  public: ~A(); }; c.cpp A::~A() { ... }
  • 2、但是只将子类的析构函数定义为虚函数,将导致core dumped,报错如下,具体原因还未知,希望有大神读到这篇文章时指点一下。 Father:1 Son:1 ~Father:1 *** Error in `./test': free(): invalid pointer: 0x...
  • 为什么标准C++建议将虚构函数定义成虚函数,下面就来探讨这个问题。 #include class Base{public: Base() {data = new char[64]; } ~Base(){delete [] data;}private: char *data;}; class BaseEx: public Base{...
  • 如标题所示,如果该类... 那么把析构函数定义成virtual有个什么意义了。确实没有多大意义,至少对于一个非delete造成的析构。无论是析构一个堆栈对象还是全局对象,编译器肯定能在编译时就做出决策了。但是,假如有
  • 析构函数可定义为纯虚函数,但也必须给出函数定义 在某些类里声明纯虚析构函数很方便。纯虚函数将产生抽象类——不能实例化的类(即不能创建此类型的对象)。有些时候,你想使一个类成为抽象类,但刚好又没有任何...
  • 什么情况下析构函数需要定义为虚函数?

    千次阅读 多人点赞 2017-09-26 08:22:12
    一、什么情况下析构函数需要定义为虚函数?答案是在实现多态时。如果单单是填空题,相信大家都可以拿满分。但说到何谓之多态,可能大家的回答不尽相同。至于多态时怎样实现的?又有什么样的作用呢?这样深入逼问下去...
  • 那我们为什么要将析构函数定义为虚函数呢?      原因是因为多态的存在。  我们大家都知道,在C++ 中,当一个对象销毁时,析构函数是用来对类对象和对象成员进行释放内存和做一些其他的cleanup操作。析...
  • C++析构函数只声明而不定义的问题

    千次阅读 2020-11-19 17:44:41
    C++析构函数只声明而不定义的问题 现附上一个简单的小例子(计算圆柱体体积) #include<iostream> using namespace std; //计算圆柱体体积 class cylinder//圆柱体 { public: double r; double h; ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 128,106
精华内容 51,242
关键字:

析构函数的定义