• C++的构造和析构函数


    一、构造函数

      1、构造函数是在创建对象时自动调用的对象,在整个对象的生命周期里,一定会被调用一次且只能被调用一次(不包括被强制调用)。

      2、在构造函数中可以负责对成员变量的初始化、分配资源、设置对象的初始状态。

      3、构造函数可以有多个版本,这些不同的版本之间会构造重载,创建对象时的方式不同、给的参数不同会调用相应的构造函数,如果调用的构造函数不存在可能会造成编译错误。

      4、如果类中没有定义构造函数,编译器会自动生成一个无参的构造函数,当自定义了一个其他版本的构造函数,则系统默认的无参函数就不会再生成。但是为了防止无参方式创建对象时出错,建议设置2个构造函数。

      5、无参构造未必无参,在C++中函数可以有默认参数,如果有参构造全部设置了默认参数,就会和无参构造有冲突,他们2个只能有一个存在。

      6、拷贝构造函数是一种特殊的构造函数,就是用一个已有的对象去构造其同类的副本对象,就是对象克隆。

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    
    class Student
    {
    
        char name[20];
        char sex;
        short age;
    public:
        Student (const char* _name,char _sex,short _age)
        {
            if(strlen(_name)<20)
            {
                strcpy(name,_name);
            }
            sex = _sex;
            age = _age;
        }
        Student(Student& that)
        {
            strcpy(name,that.name);
            sex = that.sex;
            age = that.age;
            cout << "我被调用了" <<endl;
        }
        void show(void)
        {
            cout <<name <<" "<<sex <<" "<< age<<endl;    
        }
    };
    int main()
    {
        Student stu1("hehe",'m',17);
        Student stu2 =stu1;
        stu2.show();
    }

      7、同样的,编译器也会默认生成一个拷贝构造函数,编译生成的拷贝构造函数默认会逐字节的复制类中的每一个成员。如果在类A中有类B的成员,那么在类A的拷贝构造函数中会自动调用类B的拷贝构造函数。

      8、程序员可以自定义拷贝构造来取代默认的拷贝构造,一旦自定义拷贝构造函数,那么编译器就不再生成,并且拷贝构造函数和构造函数不同的是,拷贝构造是只能有一个的,不能重载。

      9、一般情况下编译器生成的拷贝构造完全是够用的,不需要自定义拷贝构造函数。

      10、赋值构造函数就是一个对象给另一个对象赋值的时候调用的函数,与拷贝构造不同的是,对象A和B都是已经构造完成 的,此时要做的是讲B =A;而拷贝构造是需要对象A去创建对象B的。

    #include <iostream>
    #include <string.h>
    
    using namespace std;
    
    class Student
    {
        char* name;
        char sex;
            short age;
    public:
        Student(const char* _name="",char sex='f',short age=1):sex(sex),age(age)
        {
            name = new char[strlen(_name)+1];
            strcpy(name,_name);
        }
        
        Student(const Student& that)
        {
            name = new char[strlen(that.name)+1];
            strcpy(name,that.name);
            sex = that.sex;
            age = that.age;
        }
    
        
    
        void show(void)
        {
            cout << name << " " << age << endl;
        }
    
        void addAge(void) const
        {
            age++;
        }
    
        void operator = (Student& that)
        {
            if(this == &that) return;
            delete[] name;
            name = new char[strlen(that.name)+1];
            
            strcpy(name,that.name);
            sex = that.sex;
            age = that.age;
            
        }
    
        ~Student(void)
        {
            delete[] name;
        }
    };
    
    int main()
    {
        Student s1("lili",'m',33);
        s1.show();
        Student s2 = s1;
        s2.show();
        s2.addAge();
        s2.show();
        s2 = s1;
        s2.show();
    }         

      11、同样的编译器也会默认生成赋值构造函数,一般情况下默认的赋值构造也是基本够用的,除非有成员是指针,指向了额外的内存空间,这种情况我们才需要自定义拷贝构造函数和赋值构造函数。

    二、析构函数
       1、当对象被销毁时自动调用的函数叫析构函数,对象的整个生命周期中只能被调用一次,它是对象被销毁前的最后一个执行的动作。
         class 类名
         {  
          // 不能重载、只能有一个
         ///没有返回值、没有参数 
          ~类名(void)
          {
       
          }
         }
       2、编译器会默认产生一个析构函数,默认析构函数负责销毁能看的到的成员,如果有成员是类,会自动调用成员的析构函数,成员的析构过程与构行过程相反。
       3、析构函数虽然不能与重载,但可以自定义,有自定义析构函数默认析构就不会生成。
       4、当类中有析构造函数看不到的资源时(new/malloc)、有需要还愿的设置时(把打开的文件关闭/把获取到的数据保存),这时就需要自定义析构函数。


     

        

  • 相关阅读:
    Mysql 小技巧
    关于提交form不刷新的问题
    取消超链接点击默认事件
    JS获取地址栏参数
    Maven 手动添加 JAR 包到本地仓库
    Mysql函数instr、locate、position VS like
    阿里巴巴常考面试题及汇总答案
    JS跳转action
    Struts2使用ModelDriven后JSON数据返回不正确
    简单的使用AngularJS的解析JSON
  • 原文地址:https://www.cnblogs.com/yyc954330712/p/9445432.html
Copyright © 2020-2023  润新知