构造函数和析构函数

  1. 构造函数

    代码演示:

    #include<iostream>
    
    using std :: cout;
    using std :: endl;
    
    class Date
    {
    public:
    	void SetDate(int year, int month, int day)
    	{
    		_year = year;
    		_month = month;
    		_day = day;
    	}
    	void Print()
    	{
    		cout << _year << "-" << _month << "-" << _day << endl;
    	}
    private:
    	int _year;
    	int _month;
    	int _day;
    };
    
    int main()
    {
    	Date d1;
    	d1.Print(); 	//在没有初始化的情况下直接打印,会导致打印的全是随机数
    	d1.SetDate(1900, 1, 1);
    	d1.Print();
    }
    

    输出结果为:
    在这里插入图片描述
    注意:如果对象没有初始化就直接使用会接出错,为了避免这种情况,所以每个类都会有一个默认的构造函数,使得类一旦被定义出来,就已经完成了初始化,并且构造函数可以自动生成,也可以自己创建

    1.1构造函数的特性:

    构造函数是特殊的成员函数,需要注意的是,构造函数的虽然名称叫构造,但是需要注意的是构造函数的主 要任务并不是开空间创建对象,而是初始化对象。

    具体特征如下:

    1. 无返回值

    2. 函数名与类名相同

    3. **对象实例化时编译器自动调用对应的构造函数。 **

    4. 构造函数可以重载

      代码演示:

      #include<iostream>
      
      using std :: cout;
      using std :: endl;
      
      class Date
      {
      public:
      	//1.无参构造函数
      	Date()
      	{
      		cout<<"无参构造函数"<<endl;
      	}
      	//2.有参构造函数
      	Date(int year, int month, int day)
      	{
      		cout<<"有参构造函数"<<endl;
      		_year = year;
      		_month = month;
      		_day = day;
      	}
      	void Print()
      	{
      		cout << _year << "-" << _month << "-" << _day << endl;
      	}
      private:
      	int _year;
      	int _month;
      	int _day;
      };
      
      int main()
      {
      	Date d1;//调用无参构造函数,d1后面不能加括号
      	d1.Print();
      	Date d2(1900,1,1);//调用有参构造函数
      	d2.Print();
      	 //以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对像
      	Date d3();
      	//这句代码是错的,它的意思并不是在调用构造函数,而是声明d3这个函数,调用无参构造函数时,对象后不能加括号	
      }
      

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

    5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定 义编译器将不再生成

      代码演示:

      #include<iostream>
      
      using std :: cout;
      using std :: endl;
      
      class Date
      {
      public:
      	/*
      	如果用户显式定义了构造函数,编译器将不再生成
      	Date(int year,int month,int day)
      	{
      		_year=year;
      		_month=moth;
      		_day=day;
      	}
      	*/
      	void Print()
      	{
      		cout << _year << "-" << _month << "-" << _day << endl;
      	}
      private:
      	int _year;
      	int _month;
      	int _day;
      };
      
      int main()
      {
      	// 没有定义构造函数,对象也可以创建成功,因此此处调用的是编译器生成的默认构造函数 
      	Date d1;
      	d1.Print();
      }
      

      输出结果为:
      在这里插入图片描述
      注意:此时的结果竟然是随机数,这是什么原因呢?在我们自己没有创建构造函数的情况下,编译器应该会默认生成一个构造函数,但是很明显d1并没有进行初始化,难道是编译器没有默认生成构造函数吗?其实不是的,在我们自己没有创建构造函数的情况下,编译器其实默认生成了一个构造函数,但是由于它的一个特性,所以并没有初始化他的成员变量

    6. 编译器自己默认生成的构造函数只会初始化自定义类型成员变量,不会初始化内置类型的成员变量(内置类型就是语法已经定义好的类型:如 int/char…,自定义类型就是我们使用class/struct/union自己定义的类型)

      代码演示:

      #include<iostream>
      
      using std::cout;
      using std::endl;
      
      class Date2
      {
      public:
      	Date2()
      	{
      		cout << "Date2()" << endl;
      	}
      private:
      	int _year;
      	int _month;
      	int _day;
      };
      
      class Date1
      {
      public:
      	void Print()
      	{
      		cout << _year << "-" << _month << "-" << _day << endl;
      	}
      private:
      	int _year;
      	int _month;
      	int _day;
      
      	Date2 d2;
      };
      
      int main()
      {
      	Date1 d1;
      	d1.Print();
      }
      

      输出结果为:
      在这里插入图片描述
      注意:很明显编译器默认生成的构造函数会对自定类型成员变量调用的它的默认成员函数,但是对内置变量则不会进行初始化以及其它操作,所以当一个类的成员变量是内置类型的时候,则必须要自己创建一个构造函数来进行初始化

      7.无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参 构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认成员函数

      代码演示:

      #include<iostream>
      #include<stdlib.h>
      
      using std::cout;
      using std::endl;
      
      
      class Date
      {
      public:
      	Date()
      	{}
      	Date(int year = 1990, int month = 1, int day = 1)
      	{
      		_year = year;
      		_month = month;
      		_day = day;
      	}
      	void Print()
      	{
      		cout << _year << "-" << _month << "-" << _day << endl;
      	}
      private:
      	int _year;
      	int _month;
      	int _day;
      };
      
      int main()
      {
      	Date d1;
      	d1.Print();
      	system("pause");
      }
      

      输出结果:会报错,原因是出现了二义性,因为全缺省构造函数和无参数构造函数在主函数里面调用的时候都不需要实参,所以当这二者都出现在类里面的时候,在调用函数的时候就不知道到底调用哪个

  2. 析构函数

    与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作

    2.1析构函数的特性:

    1. **析构函数名是在类名前加上字符 ~ **

    2. 无参数无返回值

    3. 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数

    4. 对象生命周期结束时,C++编译系统系统自动调用析构函数

      代码演示:

      #include<iostream>
      
      using std::cout;
      using std::endl;
      
      typedef int SLDateType;
      
      class SqList
      {
      public:
      	SqList(int capacity = 20)
      	{
      		_pdate = (SLDateType*)malloc(sizeof(capacity)*capacity);
      		_size = 0;
      		_capacity = capacity;
      	}
      	~SqList()
      	{
      		if (_pdate)
      		{
      			free(_pdate);
      			_pdate = NULL;
      			_size = 0;
      			_capacity = 0;
      		}
      	}
      private:
      	int* _pdate;
      	int _size;
      	int _capacity;
      };
      

      注意:当类的成员函数有在堆上申请空间的时候,则必须要自己创建一个析构函数用来释放空间避免内存泄漏,当类里面没有在堆上申请空间的时候,则没有必要自己创建析构函数,编译器自己默认创建的析构函数就可以清理资源,因为所有的成员变量和成员函数都是在栈上创建的空间,当函数运行完后,由于栈帧的原因,在栈上开辟的所有空间都会被系统自己清理掉

    5. 编译器生成的 默认析构函数,会对自定类型成员调用它的析构函数

      代码演示:

      #define _CRT_SECURE_NO_WARNINGS
      #include<iostream>
      
      #include<iostream>
      #include<stdlib.h>
      
      using std::cout;
      using std::endl;
      
      class string
      {
      public:
      	string(const char* string = "hello world")
      	{
      		_str = (char*)malloc(strlen(string) + 1);
      		strcpy(_str, string);
      	}
      	~string()
      	{
      		free(_str);
      		cout << "string()" << endl;
      	}
      private:
      	char* _str;
      };
      
      class str
      {
      private:
      	string _str;
      	int _c;
      };
      
      int main()
      {
      	str s;
      }
      

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值