C++基础之类二(六个成员函数、构造及析构)待完善

目录

成员函数

成员函数概念

成员函数分类

构造函数

构造函数概念

构造函数十大特性

构造函数使用场景

析构函数

总结


成员函数

成员函数概念

C++中,空类并不为空,编译器会为其生成六个特殊的函数,这六个函数就是成员函数。

成员函数分类

分类

成员函数名

初始化与释放构造函数
析构函数
拷贝复制拷贝复制
赋值重载赋值重载

构造函数

构造函数概念

构造函数是C++的一种特殊函数,其作用是对象创建时完成成员变量的初始化,在对象存在期间只调用一次。

构造函数十大特性

先看一下下面的代码

class Date
{
	public:
		Date(int year,int month,int day)
	{
		_year=year;
		_month=month;
		_day=day;
	}
	void print()
	{
		printf("%d-%d-%d\n",_year,_month,_day);
	}
	private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date A(2023,10,19);
	A.print();
	return 0;
}

上端代码中,有一个特殊的函数Date(int year,int month,int day),这个函数的名字与类名相同,并且没有返回值,调用方法也与一般的函数不同,这个函数就是构造函数,它具有以下特性。

一、与类同名,构造函数Date(int year,int month,int day)的名字Date与类名相同。

二、没有返回值,Date函数没有返回值,这并不是指返回类型为void类型,不用写它的返回类型

三、自动调用,Date函数在类实例化时自动调用,实例化对象时在对象名后直接加上参数,                Date A(2023,10,19),这里需要注意,无参类型的构造函数不需要加括号,直接写Date A即可。这是因为加括号会被编译器认为是声明一个返回值为Date类型的函数。

四、构造函数可以重载

构造函数可以定义多个,只要参数类型,参数顺序等不同,都可以重载,下面的代码就是Date函数的重载,不输入参数时,成员变量初始化的值都为1。

class Date
{
	public:
		Date(int year,int month,int day)
	{
		_year=year;
		_month=month;
		_day=day;
	}
	
		Date()
	{
		_year=1;
		_month=1;
		_day=1;
	}
	void print()
	{
		printf("%d-%d-%d\n",_year,_month,_day);
	}
	private:
	int _year;
	int _month;
	int _day;
};

 五、如果不显示定义构造函数,编译器会直接生成一个构造函数,显示定义,则不会生成。

class Date
{
	public:
	
	void print()
	{
		printf("%d-%d-%d\n",_year,_month,_day);
	}
	private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date A;
	A.print();
	return 0;
}

不显示定义构造函数,编译器自行生成了默认构造函数,该函数是无参的,对成员变量是赋随机值。

六、C++定义的默认生成的构造函数区分内置类型和自定义类型,对内置类型,赋随机值,对自定义类型,调用它的默认构造函数。

上面的例子中,构造函数对内置类型变量没有作用,但是对自定义变量的类型,默认生成的构造函数相当简便

class STR
{
	public:
	STR(DateType * date=nullptr,int top=0,int capacity=0)
	{
		_date=date;
		_top=top;
		_capacity=capacity;
	}
	
	DateType * _date;
	int _top;
	int _capacity;
};


class Que
{
	public:
	void print()
	{
		printf("%d-%d\n",_push._top,_push._capacity);
		printf("%d-%d\n",_pop._top,_pop._capacity);
	}
	private:
	STR _push;
	STR _pop;
};

int main()
{
	Que A;
	A.print();
	return 0;
}

上面的代码,Que类没有显示构造函数,STR类中有默认构造函数,Que类实例化时调用了STR类类的默认构造函数,_push和_pop对象完成了初始化。

七、默认构造函数,无参与全缺省的函数,编译器生成的构造函数都是默认构造函数,默认构造函数有且只能有一个。

class STR
{
	public:
	STR(DateType * date=nullptr,int top=0,int capacity=0)
	{
		_date=date;
		_top=top;
		_capacity=capacity;
	}
	
	
		STR()
	{
		_date=nullptr;
		_top=0;
		_capacity=0;
	}
	
	DateType * _date;
	int _top;
	int _capacity;
};


class Que
{
	public:
	void print()
	{
		printf("%d-%d\n",_push._top,_push._capacity);
		printf("%d-%d\n",_pop._top,_pop._capacity);
	}
	private:
	STR _push;
	STR _pop;
};

int main()
{
	Que A;
	A.print();
	return 0;
}

 上面这段代码,有两个默认构造函数,运行时报错。

八、初始化成员列表

九、不能用const修饰

十、不能是虚函数

构造函数使用场景

实例化对象时,编译器自动调用,并且在对象的生命周期内,只调用一次。

析构函数

析构函数概念

析构函数是在对象的生命周期结束时,清理对象的成员变量的资源,析构函数不参与对象的销毁,销毁对象时编译器的事情。

析构函数六大特点

看一下下面的代码

class Stack
{
public:
	Stack(int capacity = 4)
	{
		_date = (DateType*)malloc(sizeof(DateType)*capacity);
		if (_date == nullptr)
		{
			perror("malloc fail");
			return;
		}
		_top = 0;
		_capacity = capacity;
	}
	~Stack()
	{
		free(_date);
		_date = nullptr;
		_top = 0;
		_capacity = 0;
	}
private:
	DateType* _date;
	int _top;
	int _capacity;
};

一、类名前加~

析构函数名在类名前加~。

二、无参数无返回追

析构函数没有参数与返回值。

三、一个类中有且只有一个析构函数,不显式定义,编译器会自动生成,析构函数不能重载。

四、析构函数在类对象的生命周期结束时自动调用

这里需要注意,并不是main函数结束时,而是类对象的声明周期结束

void count()
{
	Stack A;
}

int main()
{
	count();
	system("pause");
	return 0;
}

类对象A在count函数调用结束后就已经销毁,所以析构函数的调用与类的声明周期相关。

五、自动生成的析构函数只能做些基础的工作,需要资源清理,需要显式定义析构函数

以Stack类为例 

class Stack
{
public:
	Stack(int capacity = 4)
	{
		_date = (DateType*)malloc(sizeof(DateType)*capacity);
		if (_date == nullptr)
		{
			perror("malloc fail");
			return;
		}
		_top = 0;
		_capacity = capacity;
	}
	~Stack()
	{
		free(_date);
		_date = nullptr;
		_top = 0;
		_capacity = 0;
	}

显式定义析构函数,析构函数的执行结果按照代码完成,自动生成的析构函数,对内存中的资源不清理。

以Queue类为例

class Queue
{
private:
	Stack _push;
	Stack _pop;
	int _size;
};

 该类没有显式定义析构函数,但在声明周期结束时,其中自定义成员变量被清理,这是因为,自动生成的析构函数对内置类型不处理,对自定义类型会调用它的析构函数。

 六、基类的析构函数最好设置成虚函数

析构函数使用场景

析构函数在类对象生命周期结束时自动调用。

总结

构造函数与析构函数分别管理类对象的初始化与释放

构造函数没有返回值,名称与类名相同,可以重载,也可以缺省,不显示定义,编译器会自动生成无参的构造函数,但是编译器生成的对内置类型不处理,对自定义类型会调用它的默认构造函数。

默认构造函数时指无参或者全缺省的构造函数,一个类中有且只有一个默认构造函数。

析构函数与无参无返回值,函数名是类名前加~,一个类有且只有一个析构函数,不显式定义时,编译器会自动生成,但编译器生成的只能完成有限的工作,对于内置类型不处理,对于自定义类型会调用它的析构函数。

C++11中对构造函数打了补丁,对于自定义类型,可以在定义时给它一个缺省值。

class Queue
{
private:
	Stack _push;
	Stack _pop;
	int _size=4;
};

 _size那里并不是初始化赋值,而是缺省值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值