boxmoe_header_banner_img

糖画99

文章导读

类和对象(中)


avatar
mizuki 2026年5月19日 20

前言(废话)

其实已经是非常久没有写博客了,因为这一个月一直在准备蓝桥杯的比赛,所以就没有写,从今天开始将继续更新博客,顺便复习之前的c++内容

1.类的默认成员函数

  • 1.1 六大默认成员函数
  • 1.2 特性

可以手动构造默认成员函数,如果不写的话,会自动生成默认成员函数,接下来将介绍这几个默认成员函数

2.构造函数

  • 2.1 定义

不会单独开空间,而是完成对类对象的初始化

  • 2.2 特点

1.函数名与类名相同

2.无返回值

3.在对象实例化时,编译器会自动调用

4.可以函数重载,也就是可以写多个构造函数 –> 是为了实现不同方式的构造,如参数构造,迭代器构造等等

  • 2.3 默认构造函数

1.包含无参构造函数,全缺省构造函数,编译器自动生成的构造函数

2.编译器默认生成的构造函数是不稳定的,如果类的成员对象里还有自定义类对象,则会调用这个自定义类的构造函数

3.如果想让编译器强制生成默认构造函数,可以写 函数名() = defualt;

  • 2.4 构造函数的基本实现

这里给一个日期类最简单的构造函数实现:

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

	void PrintDay()
	{
		cout << _year << " " << _month << " " << _day;
	}

private:
	size_t _year;
	size_t _month;
	size_t _day;
};
  • 2.5 构造函数的基本使用

在新创建的类对象后写一个括号,再在括号内按照形参的顺序依次填入实参,如图:

  • 2.6 建议

只要能够写构造函数就一定要写,因为编译器自动生成的构造函数是未知的容易出错

3.析构函数

  • 3.1 定义

不是对对象本身的销毁,而是完成对象的资源清理工作

  • 3.2 特点

1.函数名是在类名前加一个 ~ 符号

2.无参数,无返回值

3.只能有一个析构函数

4.在对象的生命周期结束时会自动调用

5.自定义类型对象会调用对应的析构函数

6.多个自定义对象,后定义的先析构

  • 3.3 析构函数的基本实现
~Date()
{
	_year = 0;
	_month = 0;
	_day = 0;
}
  • 3.4 什么时候要写

一般来说,当成员对象中存在需要释放内存对象的时候,才需要自定义析构函数,我们也可以推断出其实上文的析构函数其实是没有必要写的,编译器自动提供的析构函数其实就已经够用了

4.拷贝构造函数

  • 4.1 定义

第一个参数为自身类类型+const的引用,C++规定传值传参必须调用拷贝构造

为什么是自身类类型+const的引用

因为如果传的是自身类类型的值,当调用构造函数时,会自动生成临时变量,而临时变量又会调用此构造函数,然后生成新的临时变量,就会陷入死循环,而引用则不会产生临时变量,const又防止了被拷贝的参数原本的值发生变化

  • 4.2 特点

1.是构造函数的重载函数

2.除第一个参数外,额外的参数必须有默认值

3.自定义类型对象拷贝必须调用拷贝构造

4.自动生成的拷贝构造会对内置类型进行拷贝,自定义类型会调用它对应的拷贝构造函数

5.对于栈这样的类,不能浅拷贝,不然会指向同一个空间

6.如果这个类需要析构,那么它就需要拷贝构造

  • 4.3 拷贝构造函数的基本实现
Date(const Date& tmp)
{
	_year = tmp._year;
	_month = tmp._month;
	_year = tmp._day;
}
  • 4.4 拷贝构造函数的基本使用

这里的两种赋值的方式都是成立的:

要注意的是,这里的day2是新创建的变量,而不是已经存在的,如果day2已经存在,则要运用到运算符重载的知识

5.运算符重载

  • 5.1 基本格式

返回类型 + operator + 运算符 + 参数

  • 5.2 特点

1.不能创造新的运算符

2..* :: sizeof ?: . 这几个不能进行运算符重载

3.不能改变内置含义(例如把减变成加)

  • 5.3 如何解决获得私有成员值的问题

1.可以写get函数来获取私有成员的值

2.写成类的成员函数,但是要少写一个参数,因为已经存在隐函数*this

3.写成友元函数,就是在函数声明的最前面加上friend,然后将此声明放在类的声明中

  • 5.4 特别注意

1.对于流插入(<<)和流输出(>>),因为参数的顺序是严格固定的,参数的第一个是ostream或istream类型,依次只能使用友元函数的方式获取私有成员的值

2.对于前置++和后置++的区分,C++规定在后置++的形参中加一个int形参(–类似)

  • 5.5 基本运算符重载的使用

1. == 和 != 的重载

bool Date::operator==(const Date& tmp)
{
	return _year == tmp._year && _month == tmp._month && _day == tmp._day;
}

bool Date::operator!=(const Date& tmp)
{
	return !(*this == tmp);
}

2. 前置++和后置++的实现

Date& operator++()
{
	_day++;
	if (_day > GetMonthday())
	{
		_month++;
		_day = 1;
	}
	if (_month > 12)
	{
		_year++;
		_month = 1;
	}
	return *this;
}

Date operator++(int)
{
	Date tmp(*this);
	operator++();
	return tmp;
}

3.输入流和输出流的实现

ostream& operator<<(ostream& out, const Date& tmp)
{
out << tmp._year << ” ” << tmp._month << ” ” << tmp._day << endl;
return out;
}

istream& operator>>(istream& in, Date& tmp)
{
in >> tmp._year >> tmp._month >> tmp._day;
return in;
}

记得在原类中加上友元函数,如图:

6.赋值运算符重载

  • 6.1定义

对于两个已经存在的对象的赋值(不是初始化!!!)

  • 6.2特点

1.建议形参用类引用+const

2.返回值存在时可以实现连续复制,建议将返回类型写成该类的引用,可以提高赋值的效率

3.自动生成的赋值运算符重载与默认拷贝重载类似,只能浅拷贝(也就是拷贝地址过去)

4.如果成员对象存在自定义对象,则会调用它自己的赋值运算符重载

  • 6.3实例
Date& Date::operator=(const Date& tmp)
{
	_year = tmp._year;
	_month = tmp._month;
	_day = tmp._day;

	return *this;
}

7.总结

相信通过本篇文章,能加深你对类和对象的理解,下一篇文章我将通过实现日期类来加强对类和对象的学习

ps:已经将近两月未写博客,最近终于稍微回到了学习的正轨,接下来我一定会定期的更新博客的!!!(其实这篇也是写到一半就没写了)



评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字

插入代码