精华内容
下载资源
问答
  • 这篇文章用于总结当析构函数是普通析构函数、虚析构函数、纯虚析构函数时,我们使用delete运算符删除一个指针对象时,析构函数会有什么情况发生;普通析构函数CBase是基类,CDerive是其子类,源码代码如下:class ...

    我们知道对象在结束其生命周期之前,都会调用析构函数以完成必要的清理工作;派生类调用的析构函数顺序是“先子类,后基类”; 这篇文章用于总结当析构函数是普通析构函数、虚析构函数、纯虚析构函数时,我们使用delete运算符删除一个指针对象时,析构函数会有什么情况发生

    ####普通析构函数####

    CBase是基类,CDerive是其子类,类源码代码如下:

    class CBase
    {
    public:
        CBase(){}
        //基类析构函数
        ~CBase(){ cout << "CBase Destructor" << endl; } 
    private:
        int a;
    };
    
    class CDerive:public CBase
    {
    public:
        CDerive(){}   
        //子类析构函数
        ~CDerive(){ cout << "CDerive Destructor" << endl; }
    private:
        int b;
    };
    

    测试代码如下:

    //case1
    CDerive *pDeriveObj = new CDerive();
    delete pDeriveObj;
    
    //case2
    //基类指针对象可以指向派生类,体现基类和派生类赋值兼容关系(不同类型可以转化和赋值),
    //但是pBaseObj只能访问基类成员,不能访问派生类成员
    CBase* pBaseObj = new CDerive();
    delete pBaseObj; //等价于删除基类对象
    

    测试结果:

    /* case 1
    先析构子类:CDerive Destructor
    后析构基类:CBase Destructor
    */
    
    /* case2
    仅析构基类:CBase Destructor
    */
    

    总结:

    1. 若delete运算符删除的是子类指针对象,则会调用子类和基类的析构函数;
    2. 若析构函数是非虚的,即使基类指针指向的是子类对象,则delete 指针对象时,也仅调用基类的析构函数

    ####虚析构函数####

    当基类中的析构函数设置为虚函数时,我们在delete 基类指针对象时,能根据实际类型完成对象的清理工作;源码如下:

    class CBase
    {
    public:
        CBase(){}
        //基类虚析构函数
        virtual ~CBase(){ cout << "CBase Destructor" << endl; } 
    private:
        int a;
    };
    
    class CDerive:public CBase
    {
    public:
        CDerive(){}   
        //子类虚析构函数
        virtual ~CDerive(){ cout << "CDerive Destructor" << endl; }
    private:
        int b;
    };
    

    测试代码:

     //指向基类对象
     CBase*pBaseObj_case1 = new CBase();
     delete pBaseObj_case1;
     
     //指向子类对象
     CBase*pBaseObj_case2 = new CDerive();
     delete pBaseObj_case2;
    

    运行结果:
    //case1
    CBase Destructor

    //case2
    CDerive Destructor ->先子类
    CBase Destructor ->后基类

    总结:
    当基类的析构函数为虚函数时,基类指针指向的是子类对象时,使用delete运算符删除指针对象,析构函能够按照“先子类,后基类”的原则完成对象清理;这样在多重继承的类中,能够保证每个类都能够得到正确的清理;比如基类和子类的缓冲区都能被释放;

    ####纯虚析构函数####

    当基类中有纯虚函数时,基类是不能被实例化的,需要在子类中重写该纯虚函数;对于纯虚析构函数有点特殊,源码如下:

    class CBase
    {
    public:
        CBase(){}
        //基类析构函数
        virtual ~CBase()= 0;
    private:
        int a;
    };
    
    class CDerive:public CBase
    {
    public:
        CDerive(){}   
        //子类析构函数
        virtual ~CDerive(){ cout << "CDerive Destructor" << endl; }
    private:
        int b;
    };
    

    测试代码:

    CBase*pBaseObj = new CDerive();
    delete pBaseObj;
    

    当我们编译代码时,会发现代码编译不过提示:
    “error LNK2019: 无法解析的外部符号 “public: virtual __thiscall CBase::~CBase(void)” (??1CBase@@UAE@XZ),该符号在函数 “public: virtual __thiscall CDerive::~CDerive(void)” (??1CDerive@@UAE@XZ) 中被引用”

    原因是子类析构时需要调用基类的析构函数,但发现代码中没有实现CBase析构函数,导致编译异常;
    解决办法就是我们在CBase类外实现其函数体,而不是在子类中重写,而且~CDerive函数也是虚函数,即使其函数名不同;这就是和其他纯虚函数有特殊的地方;

    我们需要在CBase类外增加如下的析构函数:

    CBase::~CBase()
    { 
        cout << "CBase Destructor" << endl; 
    } 
    

    这样得到的运行结果是:
    CDerive Destructor ->先子类
    CBase Destructor ->后基类

    ####总结####

    最好把基类的析构函数声明为虚函数。这将使所有派生类的析构函数自动成为虚函数。这样,如果程序中显式地用了delete运算符准备删除一个对象,而delete运算符的操作对象用了指向派生类对象的基类指针,则系统会调用相应类的析构函数。

    专业人员一般都习惯声明虚析构函数,即使基类并不需要析构函数,也显式地定义一个函数体为空的虚析构函数,以保证在撤销动态分配空间时能得到正确的处理。

    参考资料:

    http://c.biancheng.net/cpp/biancheng/view/247.html

    http://blog.csdn.net/yapian8/article/details/46418687

    展开全文
  • 析构函数定义

    万次阅读 2017-12-07 22:02:33
    析构函数往往用来做“清理善后”的工作(例如在建立对象时用new开辟了段内存空间,则在该对象消亡前应在析构函数中用delete释放这段存储空间)。 C++规定析构函数的名字是类名的前面加一波浪号(~)。其定义形式...

    1.析构函数的定义
    析构函数:当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统会自动执行析构函数。析构函数往往用来做“清理善后”的工作(例如在建立对象时用new开辟了一段内存空间,则在该对象消亡前应在析构函数中用delete释放这段存储空间)。 C++规定析构函数的名字是类名的前面加一个波浪号(~)。其定义形式为:
    ~类名(){
    函数体
    }
    析构函数不返回任何值,没有返回类型,也没有函数参数。由于没有函数参数,因此它不能被重载。换言之,一个类可以有多个构造函数,但是只能有一个析构函数

    何时调用析构函数:
    (1)对象在程序运行超出其作用域时自动撤销,撤销时自动调用该对象的析构函数。如函数中的非静态局部对象。
    (2)如果用new运算动态地建立了一个对象,那么用delete运算释放该对象时,调用该对象的析构函数。
    (3)许多类不需要显式地编写析构函数,尤其是具有构造函数的类不一定需要定义自己的析构函数。析构函数通常用于释放在构造函数或在对象生命期内获取的资源(如动态分配的内存)。
    (4)但是,析构函数的作用并不仅限于释放资源方面,它可以包含任意操作,用来执行“对象即将被撤销之前程序员所期待的任何操作
    (5)如果类需要析构函数,则该类几乎必然需要定义自己的复制构造函数和赋值运算符重载,这个规则称为析构函数三法则(rule ofthree)。

    在使用构造函数和析构函数时,需要特别注意对它们的调用时间和调用次序。

    构造函数和析构函数的调用很像一个栈的先进后出,调用析构函数的次序正好与调用构造函数的次序相反。最先被调用的构造函数,其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用,构造函数和析构函数的调用很像一个栈的先进后出,调用析构函数
    的次序正好与调用构造函数的次序相反。最先被调用的构造函数,其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。

    与复制构造函数不同,编译器总是会为类生成一个析构函数,称为合成析构函数(synthesized destructor)合成析构函数按对象创建时的逆序撤销每个非静态成员,即它是按成员在类中声明次序的逆序撤销成员的。对于类类型的每个成员,合成析构函数调用该成员的析构函数来撤销对象。需要注意,合成析构函数并不删除指针成员所指向的对象,它需要程序员显式编写析构函数去处理。

    /*************************************************************************
        > File Name: CString.cpp
        > Author: 
        > Mail: 
        > Created Time: Thu Dec  7 20:58:57 2017
     ************************************************************************/
    
    #include<iostream>
    #include<cstring>
    using namespace std;
    class CString {
        public:
        CString(const char *str);//单个参数的构造函数
        ~CString();//析构函数
        void show(){
            cout<<p<<endl;//显示字符串
    
        }
        private:
        char *p;//存储字符串动态内存区
    };
    CString::CString(const char *str)
    {
        p=new char[strlen(str)+1];//为存储str分配内存
        strcpy(p,str);//复制str到p
        cout<<"构造:"<<str<<endl;
    }
    CString::~CString(){
            cout<<"析构:"<<p<<endl;
        delete[] p;//析构函数必须是p占用的内存
    }
    int main(){
        CString s1("c++"),s2="JavaScript";//定义对象
        s1.show();
        s2.show();
        return 0;
    }
    

    这里写图片描述

    展开全文
  • C++析构函数

    2019-09-23 08:45:21
    C++析构函数 一、认识析构函数 析构函数也是一种特殊... 一个类只能有且有一个析构函数,如果没有显式的定义,系统会生成一个缺省的析构函数(合成析构函数)。 因为无参数无返回值析构函数不能重载。每有一次构...

    C++析构函数

    一、认识析构函数

    析构函数也是一种特殊的成员函数。它执行与构造函数相反的操作,通常用于撤消对象时的一些清理任务,如释放分配给对象的内存空间等。

    同样的,我们来看看析构函数的几个特点:

    • 函数名是在类名前加上~,无参数且无返回值。
    • 一个类只能有且有一个析构函数,如果没有显式的定义,系统会生成一个缺省的析构函数(合成析构函数)。
    • 因为无参数无返回值析构函数不能重载。每有一次构造函数的调用就会有一次析构函数的调用。
    • 当撤消对象时,编译系统会自动地调用析构函数。 如果程序员没有定义析构函数,系统将自动生成和调用一个默认析构函数,默认析构函数只能释放对象的数据成员所占用的空间,但不包括堆内存空间。
    class Data{
        public:
            Data(int year=2019,int month=9,int day=23):_year(year),_month(month),_day(day){}
            ~Data(){
        cout<<"~Data()"<<this<<endl;
    }
        private:
            int _year=1990;
            int _month;
            int _day;
    };
    void test(){
        Data test1;
    }
    int main(){
        test();
        return 0;
    }

    在test()函数中构造了对象d1,那么在出test()作用域d1应该被销毁,此时将调用析构函数,下面是程序的输出。当然在构建对象时是先调用构造函数的,在这里就不加以说明了。

    析构函数被调用的两种情况

    1)若一个对象被定义在一个函数体内,当这个函数结束时,析构函数会被自动调用。

    2)若一个对象在使用过程中运用new运算符进行动态创建,在使用delete释放时,自动调用析构函数。

    二、销毁操作

    析构函数在作用完类对象离开作用域后释放对象使用的资源,并销毁成员。

    void test(){
        int a=1;
        int b=2;
    }

    在一个函数体内定义一个变量,在test函数中定义a和b两个变量,在出了test函数后,a和b就会被销毁(栈上的操作)。如果是一个指向动态开辟的一块空间的指针(new,malloc),我们都需要进行free,否则就会内存泄露问题。

    当类类型对象的成员还有一个类类型对象,那么在析构函数里也会调用这个对象的析构函数。

    缺省的析构函数

    每个类都必须有一个析构函数。

    如果类中没有显式地为一个类定义析构函数,编译系统会自动地生成一个缺省的析构函数

    类名::析构函数命(){}

    class Date{
        public:
            Date(char *){
                str=new char[max_len];
        }
        ~Date(){ delete []str;}
        void get_info(char *);
        void send_info(char *);
        private:
            char *str;
            int max_len;
    };

    析构函数阻止该类型对象被销毁

    我们如果不想要析构函数来对对象进行释放该怎么做呢,不显式的定义显然是不行的,因为编译器会生成默认的合成析构函数。之前我们知道了如果想让系统默认生成自己的构造函数可以利用default,那么其实还有一个东西叫做delete。

    class Date{
        public:
           Date(int year=2019,int month=9,int day=1):_year(year),_month(month),_day(day){}
            ~Date()=delete;
        private:
            int _year=2019;
            int _month;
            int _day;
    };

    这么写了,又在底下创建Date类型的对象,那么这个对象将是无法被销毁的,其实编译器并不允许这么做,直接会给我们报错。

    但可以使用动态创建这个类类型对象的,像这样:Date* p = new Date;虽然这样是可行的,但当你delete p的时候依然会出错。既不能定义一个对象也不能释放动态分配的对象,所以还是不要这么用为好。

    一般在显式的定义了析构函数的情况下,应该也把拷贝构造函数和赋值操作显式的定义。

    class Date{
        public:
           Date(int year=2019,int month=9,int day=1):_year(year),_month(month),_day(day){
                p=new int;
    }
            ~Date(){
                delete p;
    }
        private:
            int _year=2019;
            int _month;
            int _day;
            int *p;
    };

    成员中有动态开辟的指针成员,在析构函数中对它进行了delete,如果不显式的定义拷贝构造函数,当你这样:Date d2(d1)来创建d2,我们都知道默认的拷贝构造函数是浅拷贝,那么这么做的结果就会是d2的成员p和d1的p是指向同一块空间的,那么调用析构函数的时候回导致用一块空间被释放两次,程序会崩溃。

     

    调用构造函数与析构函数的顺序

    1)一般顺序

    调用析构函数的次序正好与调用构造函数的次序相反,最先被调用的构造函数,其对应的构造函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。

    对象1构造函数->对象2的构造函数->对象3的构造函数->对象3的析构函数->对象2的析构函数->对象1的析构函数

    2)全局对象

    在全局范围中定义的对象(即在所有函数之外定义的对象),它的构造函数在所有函数执行之前调用。在程序流程离开其作用域时,调用该全局对象的析构函数。(包括main函数)

    3)auto局部对象

    局部自动对象(例函数中定义的对象),则在建立对象时调用其构造函数。如果函数被多次调用,则每次调用时都要调用构造函数。在函数调用结束、对象释放时先调用析构函数。

    4)static局部对象

    在函数中定义静态局部对象,则只在程序第一次盗用此函数建立对象时调用构造函数一次,在调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用析构函数。

    对象的生存期

    对象生存期不同分为:局部对象、全局对象、静态对象、动态对象。

    (1)局部对象

    当对象被定义时,调用构造函数,该对象被创建;当程序退出该对象所在的函数体或程序块时,调用析构函数,对象被释放。

    局部对象在被定义在一个函数体或程序块内的,它的作用域限定在函数体或程序块内,生存期比较短。

    (2)全局对象

    当程序开始运行时,调用构造函数,该对象被创建;当程序结束时,调用析构函数,该对象被释放。

    静态对象时被定义在一个文件中,它的作用域从定义是起到文件结束为止,生存期长。

    (3)静态对象

    当程序中定义静态对象时,调用构造函数,该对象被创建;当整个程序结束时,调用析构函数,对象被释放。

    全局对象是被定义在某个文件中,它的作用域包含在该文件的整个程序中,生存期最长。

    (4)动态对象

    执行new运算符调用构造函数,动态对象被创建;用delete释放对象时,调用析构函数

    动态对象由程序员掌握,它作用域与生存期是有new和delete之间的时间决定的。

     

    展开全文
  • C++中为什么在共有继承时,要将基类的对象定义成员虚函数,就是因为:在...有因为析构函数不能被继承到派生,所以要定义为虚函数。 可以看看这博主写的: http://blog.sina.com.cn/s/blog_7c773cc50100y9hz.htm...

    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#析构函数

    千次阅读 2017-01-11 19:04:36
    不能在结构中定义析构函数只能对类使用析构函数。 一个类只能有一个析构函数。 无法继承或重载析构函数。 无法调用析构函数。它们是被自动调用的。 析构函数既没有修饰符,也没有参数。 例如,下面是类...
  • 如果没有定义析构函数,那么只有中含有成员对象(或者本的基类)拥有析构函数的情况下,编译器才会合成一个出来,否则析构函数被视为不要,也就不需要合成。例如,如下,虽然Point拥有虚函数:[cpp] view...
  • C++ 析构函数

    万次阅读 多人点赞 2016-09-21 00:02:15
    C++ 析构函数我使用的继承开发环境: Visual Studio 2010设计一个类时,如何写析构函数析构函数如果我们不写的话,C++ 会帮我们自动的合成一个,就是说:C++ 会自动的帮我们写一个析构函数。很多时候,自动生成...
  • 我知道,基类的析构函数要生命为虚函数,不然用基类指针删除派生对象时只会调用基类的析构函数,而不会调用派生析构函数,从而发生内存泄露。但是为什么会这样?为什么基类析构函数不是虚函数时,就不会调用...
  • 析构函数的作用及合成析构函数

    千次阅读 2013-11-30 02:05:33
    析构函数 用于释放在构造函数或在对象生命期内获取的资源。 如果需要析构函数,那么也需要复制操作符和复制构造函数。...编译器总是为我们合成一个析构函数,合成析构函数按对象创建时的逆序撤销每个非static成员,
  • C++析构函数调用和虚析构函数

    千次阅读 2013-11-13 08:48:40
    析构函数一般是自动调用的,但是某些情况下页需要显式调用,如出栈和入栈操作: void C::push_back(const X& a) { // ... new(p) X{a}; // copy constr uct an X with the value a in address p // ... }   void C:...
  • 析构函数:当且仅当里包含至少一个虚函数的时候才去声明虚析构函数,无故的声明虚析构函数和永远不去声明一样是错误的; class <类名> { virtual ~<类名>(); … }; 即:virtual ~A(); 纯虚析构函数:抽象是...
  • C++中析构函数为虚函数

    千次阅读 多人点赞 2019-04-12 23:13:17
    1、析构函数是否定义为虚函数的区别 (1)析构函数定义为虚...(2)析构函数定义为虚函数时:编译器实施静态绑定,在删除基类指针时,只会调用基类的析构函数而不调用派生类析构函数,这样就会造成派生对象析...
  • 析构函数

    千次阅读 2018-08-01 19:45:58
    1)构造函数可以有多个来构成重载,但析构函数只能一个,不能构成重载 2)构造函数可以有参数,但析构函数不能有参数 3)与构造函数相同的是,如果我们没有显式的写出析构函数,那么编译器也会自动的给我们加上...
  • 在看代码的过程中,有时会发现析构函数定义成virtual,有一些没有定义成virtual但被放置于protected下。网上搜了下了解了原因,下面是较好的...1、如果一个类被继承,同时定义了基类以外的成员对象,且基类析构函数
  • 很多情况下要求当前的程序中只有一个object。... 当我们在程序中声明一个对象时,编译器为调用构造函数(如果有的话),而这个调用将通常是外部的,也就是说它不属于class对象本身的调用,假如构造函数是私
  • 默认构造函数指不带参数或者所有参数都有缺省值的构造函数!!! (1)构造函数、析构函数与赋值函数 ...构造函数、析构函数与赋值函数是每个类最基本的函数。它们太普通以致让人容易...对于任意一个类A,如果不编写上述
  • C++:什么情况下需要将析构函数定义为虚函数。
  • 2:可能是基类的指针指向派生的对象,当析构一个指向派生的成员的基类指针,这时程序不知道这么办,可能会造成内存的泄露,因此此时基类的析构函数定义为虚函数; 基类指针可以指向派生的对象(多态),...
  • 1. 析构函数和虚析构函数 如果基类的析构函数是虚的,那么它的派生析构函数都是虚的 这将导致:当派生析构的时候,它的所有的基类的析构函数都将得到调用 否则,只调用派生析构函数(这可能导致基类的...
  • 私有析构函数

    2015-01-09 21:56:44
    析构函数定义为私有成员可以保证只能在堆上new一个新的对象. 下面写一个简单的例子验证一下: 写一个简单的,把它的析构函数变成私有的. new一个新的对象,编译通过,如下图. 把原来的代码改动一下,直接在...
  • 什么情况下析构函数需要定义为虚函数?

    千次阅读 多人点赞 2017-09-26 08:22:12
    、什么情况下析构函数需要定义为虚函数?答案是在实现多态时。如果单单是填空题,相信大家都可以拿满分。但说到何谓之多态,可能大家的回答不尽相同。至于多态时怎样实现的?又有什么样的作用呢?这样深入逼问下去...
  • 前言,在c++面试过程中,最能考察类的基础知识的莫过于写一个具有类的必要函数的类。...定义一个类如下 class String { public: String(const char *str=NULL); ~String(); String(const String &others);
  • 浅谈析构函数

    2015-04-22 11:18:31
    一个类只能有一个析构函数析构函数没有返回类型,也没有参数。析构函数的名称是在类名称前面加上~。 如果构造函数使用new来分配内存,则必须提供使用delete的析构函数来释放这些内存。 下述情况下,析构...
  • C++《析构函数定义和使用》

    千次阅读 2013-07-17 14:25:30
    析构函数(destructor)也是一个特殊的成员函数,它的作用与构造函数相反,它的名字是类名的前面加一个“~”符号。 在C++中“~”是位取反运算符,从这点也可以想到:析构函数是与构造函数作用相反的函数。当对象...
  • C++函数之的构造函数析构函数

    千次阅读 2015-02-25 10:01:59
    对于类对象成员的初始化我们始终是...关于C++类成员的初始化,有专门的构造函数来进行自动操作而无需要手工调用,在正式讲解之前先看看c++对构造函数一个基本定义:  1,C++规定,每个类必须有默认的构造函数,没
  • C++将析构函数为啥需要定义成virtual

    千次阅读 2018-02-11 09:43:49
    一般来说,如果一个类要被另外一个类继承,而且用其指针指向其子类对象时,如题目中的A* d = new B();(假定A是基类,B是从A继承而来的派生类),那么其(A类)析构函数必须是虚的,否则在delete d时,B类的析构函数将...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 57,989
精华内容 23,195
关键字:

一个类只能定义一个析构函数