【C++】类的默认构造函数

类的默认成员函数

文章目录

  • 类的默认成员函数
    • 1. 构造函数
    • 2. 默认构造函数
    • 3. 析构函数
    • 4. 拷贝/复制构造函数

1. 构造函数

初始化类

  • 函数名与类名相同
  • 无返回值
  • 对象实例化时编译器自动调用对应的构造函数
  • 构造函数可以重载

我们测试一下对象实例化时编译器自动调用对应的构造函数

#include 
using namespace std;

class Date
{
public:
    //含参的构造函数
	Date(int year = 0, int month = 0, int day = 0)
	{
		_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();

	return 0;
}

【C++】类的默认构造函数_第1张图片


测试一下构造函数可以重载

class Date
{
public:

	Date()
	{
		_year = 0;
		_month = 0;
		_day = 0;
	}

	Date(int year = 0, int month = 0, int day = 0)
	{
		_year = year;
		_month = month;
		_day = day;

	}

	void print()
	{
		cout << _year << "-" << _month  << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;//这里使用的时候存在歧义
	Date d2(2022,1,21);

	return 0;
}

【C++】类的默认构造函数_第2张图片

可以构成重载,但能否使用另外说明

可以改成

Date()
{
	_year = 0;
	_month = 0;
	_day = 0;
}

Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;

}

//上面两个函数其实等价于下面一个函数

Date(int year = 0, int month = 0, int day = 0)
{
	_year = year;
	_month = month;
	_day = day;

}

2. 默认构造函数

如果我们自己没有写构造函数,类会自己生成一个构造函数初始化

【C++】类的默认构造函数_第3张图片

但数据显示根本没有给我初始化0

原因:C++中类分为两个内置类型(基本类型),自定义类型

  • 内置类型:int char double指针 数组等
  • 自定义类型: struct class定义的类型

如果我们不写构造函数,编译器默认生成构造函数,并且对内置类型不作初始化处理,而对自定义类型,会去寻找自定义类型的默认构造函数(没有参数就可以访问的构造函数),如果没有则会报错

【C++】类的默认构造函数_第4张图片

有默认构造函数时,没有错误,无默认构造函数时,(全缺省可以)半缺省以及要传参数会出错

所以有三种:不会报错的

  • 全缺省
  • 无参
  • 不写(程序自动生成,但是无用默认构造函数(什么都不做))
  • 但默认构造函数,有且只能有一个
  • 【C++】类的默认构造函数_第5张图片

歧义:【C++】类的默认构造函数_第6张图片

可能你想不传参定义对象,但这里对象创建的时d1()


例子:在类里面定义一个自定义类型的成员变量st

当我们一步一步调试的时候,在初始化类里面内置类型之前,先初始化了自定义类型的成员变量st

#include 
using namespace std;

class st
{
public:
	st()
	{
		a = 0;
		b = 0;
	}
private:

	int a;
	int b;
};

class Date
{
public:

	Date(int year = 0, int month = 0, int day = 0)
	{
		_year = year;
		_month = month;
		_day = day;

	}

	void print()
	{
		cout << _year << "-" << _month  << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
	st ST;
};

int main()
{
	Date d1;
	return 0;
}

3. 析构函数

对象在销毁时会自动调用析构函数

  • 析构函数名是在类名前加上字符 ~
  • 无参数无返回值
  • 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。 (因为没有参数,所以不构成函数重载)
  • 对象生命周期结束时,C++编译系统系统自动调用析构函数。比如return 0的时候,看的是定义

用栈去解释

class Stack
{
public:
    //初始化栈
	Stack(int capacity = 4)
	{
		_a = (int*)malloc(sizeof(int) * capacity);

		if (_a = nullptr)
		{
			cout << "malloc fail" << endl;
			exit(-1);
		}
		_capacity = capacity;
		_top = 0;
	}
    //销毁栈
	~Stack()
	{
		free(_a);
		_a = nullptr;
		_capacity = 0;
		_top = 0;
	}
private:
	int* _a;//数组,动态栈
	int _top;//栈顶
	int _capacity;//栈大小
};

int main()
{
	Stack d1;
    Stack d2;
	return 0;
}
  • 因为是栈,后进先出,初始化顺序先d1后d2,销毁顺序先d2,后d1

再利用上面年月日的例子

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;

	}

	~Date()
	{
		_year = 0;
		_month = 0;
		_day = 0;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;
	return 0;
}

可以在运行的时候发现,Date d1;走完之后,年月日都为1(构造函数)return 0;之前,年月日变为0,将析构函数删除后,不会变为0,编译器并没有像析构函数那样帮我们销毁(重新初始化)

【C++】类的默认构造函数_第7张图片

可见析构函数跟构造函数一样,不写的话,默认构造函数/析构函数不会起什么作用,同样是内置类型不作处理,自定义类型需要调用对应的析构函数。

关于为什么C++不作处理

像指针

int* a;//普通指针
FILE* x;//文件指针

如果free掉文件指针会出大问题,有些是不需要它free的,所以对内置类型不作处理,对自定义类型需要默认的析构函数


4. 拷贝/复制构造函数

  • 首先它和类名相同,没有返回值,这就意味着它跟构造函数构成函数重载
  • 参数只有一个,并且是引用传参,否则会造成无限拷贝构造(传值需要拷贝)
  • 传引用不需要调用拷贝构造
Date(const Date& d)
{
	_year = d._year;
	_day = d._day;
	_month = d._month;
}

  • 对于内置类型,按字节拷贝(浅拷贝)
  • 如果成员有是数组指针,
Stack st1;
// 拷贝复制
Stack st2(st1);
  • 这里st2拷贝了st1的指针,当修改其数组中元素时,st1也会被修改,我们需要的是独立的类
  • 如果内置类型是指针,如果是动态开辟的指针,不能被free两次
  • 但如果自己不写free,默认的析构函数不会去free动态开辟的指针
  • 自定义类型调用自己的拷贝构造

你可能感兴趣的:(C++,programing,langua,c++,开发语言,后端)