【C++---3】类与对象(中)

类的6个默认成员函数:

如果一个类中,一个成员也没有,这个类被简称为空类,空类中并不是什么都没有,任何一个类在我们什么都不写的情况下都会生成6个默认的成员函数

在这里插入图片描述

#include<iostream>

using namespace std;

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

		void PrintDate()
		{
			cout << _year << "-" << _month << "-" << _day << endl;
		}

private:
		int _year;
		int _month;
		int _day;

};

int main()
{
		Date d1;
		d1.setDate(2019, 6, 16);
		d1.PrintDate();

		Date d2;
		d2.setDate();
		d2.PrintDate();

		system("pause");
		return 0;
}

对于以上日期类,每次创建对象都需要使用setdate设置太过于麻烦


构造函数:

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次

构造函数的主要任务是初始化对象,不是构造对象

初始化在函数后面加:,然后进行初始化

特征:

1.函数名与类名一致
2.没有返回值
3.编译器自动调用
4.可以重载

代码示例:

#include<iostream>

using namespace std;

class Date
{
public:
		//无参构造函数
		Date()
		{

		}

		//有参构造函数
		Date(int year,int month,int day)
		{
			_year = year;
			_month = month;
			_day = day;
		}

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

int main()
{
		Date d1;
		d1.PrintDate();
	
		Date d2(2019, 6, 16);
		d2.PrintDate();

		system("pause");
		return 0;
}

d1调用无参构造函数的时候不用加括号,否则就变成函数声明了

有参构造函数如果写成全缺省函数就会报错,类中包含多个默认构造函数

如果用户没有显式定义一个构造函数,编译器会自动生成一个无参的构造函数


析构函数:

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

特性:

1.析构函数名是类名加上~
2.既没有参数也没有返回值
3.一个类有且只有一个析构函数,如果没有显式定义,系统会自动生成默认的析构函数
4.对象声明周期结束时,C++编译系统会自动调用析构函数

代码示例:

typedef int Datatype;

class Seqlist
{
public:
		Seqlist(int capacity)
		{
			_array = (Datatype*)malloc(sizeof(Datatype));
			_size = 0;
			_capacity = capacity;
		}

		~Seqlist()
		{
			if (_array)
			{
				free(_array);
				_array = NULL;
				_size = 0;
				_capacity = 0;
			}
		}

private:
		int* _array;
		int _size;
		int _capacity;
};

拷贝构造函数:

只有单个形参,该形参是对本类类型对象的引用,在用已存在的类类型对象创建新对象时由编译器自动调用

特征:

拷贝构造函数也是特殊的成员函数

1.拷贝构造函数是构造函数的一种重载形式
2.拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会导致无限递归

默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种被称为浅拷贝

	单参数(const类类型&)--->如果没有按照&方式提供:编译器编译失败,导致无限递归

如果没有显式定义,系统生成默认的拷贝构造函数

代码示例:

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

		void PrintDate()
		{
			cout << _year << "-" << _month << "-" << _day << endl;
		}

		Date(const Date& d)
		{
			_year=d._year ;
			_month = d._month;
			_day = d._day;
		}

private:
		int _year;
		int _month;
		int _day;

};

int main()
{
		Date d1;
		Date d2(d1);

		d1.PrintDate();
		d2.PrintDate();

		system("pause");
		return 0;
}

默认拷贝构造函数:浅拷贝— 将一个对象中内容原封不动的拷贝到另一个对象中

	Date--->编译器生成的默认拷贝构造

	String---默认拷贝构造函数---一定会出错

当作成员函数的话,参数有当前默认的对象,所以只传一个参数就可以


赋值运算符重载:

运算符重载是具有特殊函数名的函数

函数名字为:关键字operator后面接需要重载的运算符符号
函数原型:返回值类型 operator操作符(参数列表)

以下运算符不可以重载:

		.*		::		sizeof		?:		. 

运算符的重载参数必须至少有一个类类型的操作数,不然可能造成无限递归

	不可以改变内置整形本身的含义,+号不改变值,只返回结果,创建一个临时的变量

	只能按照值的方式返回,不能返回引用

如果是自定义类型的,返回优先考虑引用,只需要考虑周期有没有函数的长

赋值运算符的参数类型是const类型的引用,因为不需要改变内容

实现步骤:

1.参数类型
2.返回值
3.检测是否自己给自己赋值
4.返回*this

函数后面加const,不允许修改成员变量的值

代码示例:

==的重载

class Date
{
public:
		Date(int year = 1900, int month = 1, int day = 1)
		{
			_year = year;
			_month = month;
			_day = day;
		}
	
		void PrintDate()
		{
			cout << _year << "-" << _month << "-" << _day << endl;
		}

		Date(const Date& d)
		{
			_year=d._year ;
			_month = d._month;
			_day = d._day;
		}

		bool operator==(const Date& d)
		{
			if (_year == d._year&&
				_month == d._month&&
				_day == d._day)
			{
				return true;
			}
			return false;
		}

		bool operator!=(const Date& d)
		{
			if (!(_year == d._year&&
				_month == d._month&&
				_day == d._day))
			{
				return true;
			}
			return false;
		}

private:
		int _year;
		int _month;
		int _day;

};

int main()
{
		Date d1;
		Date d2(d1);

		d1.PrintDate();
		d2.PrintDate();

		Date d3(d1);
		Date d4(2019, 6, 16);

		d3.PrintDate();
		d4.PrintDate();
	
		if (d1 == d2)
		{
			cout << "d1与d2日期一致" << endl;
		}

		if (d3 != d4)
		{
			cout << "d3与d4日期不一致" << endl;
		}

		system("pause");
		return 0;
}

=的重载

	Date& operator=(const Date& d)
	{
			if (this != &d)
			{
				_year = d._year;
				_month = d._month;
				_day = d._day;
			}
			return *this;
	}

+的重载

	Date operator+(int days)
	{
			Date tmp(*this);
			tmp._day += days;
			return tmp;
	}

这里的返回值不能是引用,因为tmp是栈上的,生命周期是函数的调用到结束

前置++的重载

	Date& operator++()
	{
			_day + 1;
			return *this;
	}

对象的生命周期比函数长,可以返回引用

后置++的重载

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

参数类型给成int是为了和前置++形成重载


const成员函数:

将const修饰的类成员函数称为const成员函数,const实际修饰的是this指针,表明该成员函数不可以修改类中的任何成员变量

在这里插入图片描述
const相当于限制this指针,表明当前对象的内容不可以被修改

const Date* const

1. const对象可以调用非const成员函数吗?

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

		void TestFunc()
		{
			_day = 1;
		}
		
private:
		int _year;
		int _month;
		int _day;
		
};

int main()
{
		const Date d(2019, 6, 16);
		d.TestFunc();

		system("pause");
		return 0;
}

在这里插入图片描述
非const成员函数可以对类里的成员变量进行修改,如果可以调用,那么限制就失去意义,代码不安全

2. 非const对象可以调用const成员函数吗?

	void TestFunc()const
	{

	}

在这里插入图片描述
d的成员变量相当于可读写,TestFunc函数相当于只读函数,d此时可以被TestFunc读,可以调用,但是不可以通过TestFunc写

3. const成员函数内可以调用其它的非const成员函数吗?
在这里插入图片描述
const成员函数只可以读不可以写,而非const成员函数是可以写也可以读的,如果可以调用,代码不安全

4. 非const成员函数内可以调用其它的const成员函数吗?

不想贴图了,可读可写的函数调用一个只可以读的函数,没什么不安全的对吧?肯定是可以的


取地址及const取地址操作符重载:

一般函数代码示例:

	Date* operator&()
	{
			return this;
	}

const类型的&,如果可以调用&的重载,就可以修改成员变量的值,会矛盾

const类型的对象不能调用此类型的函数

const成员函数代码示例:

	const Date* operator&()const
	{
			return this;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值