C++类与对象:初识(默认)构造函数与析构函数

这里写目录标题

    • 构造函数
      • 默认构造函数
    • 对象的初始化和赋值
    • 析构函数 :
      • 默认析构函数
    • 总结:

对于Date类,可以通过SetDate公有的方法给对象设置内容,但是如果每次创建对象都调用该方法设置信息过于麻烦,那能否在对象创建时,就将信息设置进去呢?

构造函数

构造函数特征:

  1. 名字与类名相同;
  2. 没有返回值类型,也不用写类型;
  3. 在创建对象时编译器自动调用;
  4. 在整个对象的生命周期只调用一次;
  5. 构造函数可以重载;
  6. 只是给对象中成员变量初始化,而不是给对象开辟空间

C++类与对象:初识(默认)构造函数与析构函数_第1张图片
类的6个默认成员函数:程序员没有写会由编译器直接提供,C11又增加了两个

单参的构造函数有特殊的性质

默认构造函数

对于内置类型的成员变量 不做处理
对于自定义类型的成员变量 处理,处理方式就是调用该类型的构造函数

默认构造函数是为没有提供显式初始值,用来创建对象的构造函数

默认构造函数有3种,全缺省,无参,编译器自动生成:

  1. 全缺省:
    Date (int year=2021, int month=7 , int day=11 );
  2. 无参:
    Date () {}
    同编译器自动生成的构造函数体
    没有参数,但是函数体可以有代码;

都是为了给Date d这种对象初始化

如果没有定义构造函数,编译器会自动生成一个无参构造函数Date (){}

  • 这就是自动生成默认构造函数,不做任何工作;
  • 如果构造函数已定义编译器则不会再去定义;
  • 编译器生成的无参构造函数表面上是不做任何工作,但是编译器还是进行赋值,值是随机值
    因为禁止创建未初始化的对象

编译器自动生成无参构造函数的时机

  • 在没有定义任何构造函数时,编译器才会提供默认构造函数;
  • 如果定义了这种对象Date d1;
    并且程序员定义了一个构造函数,就必须再定义默认构造函数;

C++类与对象:初识(默认)构造函数与析构函数_第2张图片
在这里插入图片描述

对象的初始化和赋值

初始化和赋值区别在下一篇文章

1.直接初始化

  • Date d1(2015, 1, 1);
    创建一个名为d的Date对象,并将数据成员初始化;

2.通过其它对象初始化(会产生临时对象,代码如上所示)

  • 这里会牵扯到一些运算符重载的知识

Date d2 = d(2021, 7, 11);C++标准允许编译器使用两种方式来执行d初始化:

  • 一种与对象d2初始化方式相同;

  • 另一种构造函数创建一个临时对象d,将该临时对象赋值到d2中,并丢弃临时变量;如果编译器使用这种方式,则临时对象会调用析构函数

要保证d不会再用于其余方面

(3).对象之间的相互赋值(编译器对赋值运算符进行了重载)
d2 = d1;或者 d2 = d(2021, 7, 11);该语句表明:可以将一个对象的成员复制给另一个对象,d2原内容被覆盖

(4).构造函数不仅可以构造与初始化对象,对于单个参数的构造函数,还具有类型转换的作用

  • 用explicit修饰构造函数,将会禁止单参构造函数的隐式转换
class Date
{
public:
	Date(int year):_year(year)
	{}
	Date& operator=(const date& d)
	{
		if(this != &d)
			_year=d._year;
		return *this;
	}
private:
	int _year;
}
int main ()
{
	Date d1(2021);
	d1=2022;
	return 0;
}
  • d1=2022;执行该语句时,编译器发现两侧类型不一样,并且还有一个单参的构造函数;
  • 编译器就会用右侧的2022借助单参构造函数创建一个匿名对象,再用已构造好的对象给d1赋值,不是2022给d1赋值;
  • 这种情况只出现于单参的构造函数,要避免这种情况发生,需要关键字explicit,加上后 d1=2022;执行该语句时报错

析构函数 :

析构函数是在对象销毁时被自动调用的,用于执行清理工作,包括释放动态内存、关闭文件和网络连接等操作,最终将对象从内存中销毁
只是清理对象中成员变量所占用资源的释放

特征:

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数,无返回值。
  3. 一个类有且只有一个析构函数。若用户未定义,系统会自动生成默认的析构函数。
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数,在对象销毁的时候自动调用。
  5. 析构函数不能重载,参数列表不符合函数重载的条件

调用析构函数的时机(由编译器决定):

  1. 创建的是静态存储类对象,析构函数将在程序结束时自动被调用。
  2. 创建的是自动存储类对象,析构函数将在程序执行完代码块时(该对象是在其中定义的)自动被调用。
  3. 对象是通过new创建的,则它将驻留在栈内存或自由存储区中,当使用delete来释放内存时,析构函数将自动被调用。

默认析构函数

默认析构函数的行为取决于类中成员变量的类型

  • 内置类型成员,默认析构函数不需要执行任何操作
    因为内置类型的成员变量不需要手动释放内存
    默认析构函数只是将该对象的内存空间回收给操作系统,不会对其成员变量进行任何处理
  • 指针类型成员,这些指针指向动态分配的内存,
    默认析构函数只会释放这些指针本身占用的内存,而不会释放它们所指向的内存块
    这种情况最好显式定义析构函数,释放内存
  • 对于自定义类型成员,默认的析构函数只会调用该类成员变量的析构函数

总结:

1.Date d2 = d(2021, 7, 11)这条语句是初始化(虽然会创建临时变量)
d2 = d(2021, 7, 11)这一条语句是赋值(赋值运算符的重载)
2.匿名对象属于临时对象

3.调用析构函数的顺序:
main函数结束后,局部变量d1和d2将消失,由于变量被存放在栈中
后创建的对象先删除,先创建的对象后删除

你可能感兴趣的:(C++,c++)