类的默认成员函数(构造函数,析构函数,拷贝构造函数,赋值运算符重载,取地址运算符重载,const取地址运算符重载)

类的默认成员函数

类的默认成员函数
1、负责初始化和清理工作的,构造函数负责初始化,析构函数负责清理
2、拷贝复制,拷贝构造函数是使用同类对象初始化创建对象,赋值运算符重载主要是把一个对象赋值给另一个对象。
3、取地址运算符重载,包含取地址运算符重载和const取地址运算符重载。

1、构造函数

1.1、构造函数概念

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

1.2、构造函数特性

1、函数名与类名相同
2、无返回值
3、对象实例化编译器自动调用对应的构造函数
4、构造函数可以重载
5、如果类中没有显示定义构造函数,则C++编译器会自动生成一个构造函数,一旦用户显示定义,编译器将不再生成
6、无参构造函数和全缺省参数的构造函数都称为默认构造函数,并且默认构造函数只能有一个。

#include 

using namespace std;

class Date1
{
public:
	void Display()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
	void SetDate(int yeay, int month, int day)
	{
		_year = yeay;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

class Date2
{
public:
	//无参构造
	Date2 ()
	{

	}
	//带参构造
	Date2 (int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

void TestDate2()
{
	Date2 d3;//调用无参构造
	Date2 d4(2020, 3, 27);//调用带参构造

	//注意:调用无参构造不能带括号,不然会当成函数声明
	Date2 d5();//会被当做函数d5无参,返回Date类的函数声明。
}

class Date3
{
public:
	////无参构造
	//Date3 ()
	//{

	//}
	////带参构造
	//Date3 (int year, int month, int day)
	//{
	//	_year = year;
	//	_month = month;
	//	_day = day;
	//}
private:
	int _year;
	int _month;
	int _day;
};

void TestDate3()
{
	Date3 d6;//此处调用的是类的默认构造函数,故可以成功创建对象。
}

class Date4
{
public:
	//无参构造
	Date4 ()
	{
		_year = 2020;
		_month = 3;
		_day = 27;
	}
	//全缺省参数构造
	Date4 (int year = 2020, int month = 3, int day = 27)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

void TestDate4()
{
	//Date4 d;//报错,因为Date4中含有多个构造函数,创建对象时不知该调用哪个。
}

class Time
{
public:
	Time()
	{
		cout << "Time ()" << endl;
	}

	Time()
	{
		_hour = 0;
		_minute = 0;
		_second = 0;
	}

private:
	int _hour;
	int _minute;
	int _second;

};

class Date5
{
private:
	//内置类型
	int _year;
	int _month;
	int _day;
	//自定义类型
	Time _t;
};

void TestDate5()
{
	Date5 d5;
}

//成员变量的命名风格
class Date6
{
public:
	Date6(int year)
	{
		_year = year;
	}
private:
	int _year;
};

//成员变量的另外一种命名风格
class Date7
{
public:
	Date7 (int year)
	{
		m_year = year;
	}
private:
	int m_year;
};

int main()
{
	Date1 d1, d2;

	d1.SetDate(2020, 1, 24);
	d2.SetDate(2020, 3, 26);

	d1.Display();
	d2.Display();

	system("pause");
	return 0;
}

2、析构函数

2.1、析构函数概念

析构函数是对象在销毁时候回自动调用析构函数,完成一些资源的释放工作。

2.2、析构函数特征

1、析构函数名是在类名称前面加上~
2、无参数无返回值
3、一个类有且只有一个析构函数,若未现实定义,有编译器给出默认析构函数
4、对象生命周期结束时,C++编译器自动调用析构函数。

#define _CRT_SECURE_NO_WARNINGS

#include 
#include 
#include 

using namespace std;

typedef int DataType;

class SeqList
{
public:
	SeqList(int capacity = 10)
	{
		_SeqList = (DataType*)malloc(capacity * sizeof(DataType));
		assert(_SeqList);
		_size = 0;
		_capacity = capacity;
	}

	~SeqList()
	{
		if (_SeqList)
		{
			free(_SeqList);
			_SeqList = NULL;
			_capacity = 0;
			_size = 0;
		}
	}

private:
	DataType* _SeqList;
	size_t _size;
	size_t _capacity;
};

class String
{
public:
	String(const char* str = "zhangsan")
	{
		_str = (char*)malloc(strlen(str) + 1);
		strcpy(_str, str);
	}

	~String()
	{
		cout << "~String()" << endl;
		free(_str);
		_str = NULL;
	}

private:
	char* _str;
};

class Person
{
private:
	String _name;
	int _age;
};

int main()
{
	String _name;
	Person per;

	system("pause");
	return 0;
}

3、拷贝构造函数

3.1、拷贝构造函数的概念

只有一个形参,该形参是对本类类型对象的引用(一般常用const修饰),在已存在的类类型对象创建新对象时由编译器自动调用。
3.2、拷贝构造函数的特征
1、拷贝构造函数是构造函数的一个重载形式
2、拷贝构造函数的参数只有一个且必须使用引用传参(防止无限递归)。
3、若未显示定义,则系统默认生成的拷贝构造函数为浅拷贝。(对象按内存存储的字节序完成拷贝)。

#define _CRT_SECURE_NO_WARNINGS

#include 
#include 

using namespace std;

class Date1
{
public:
	Date1(int year = 2020, int month = 3, int day = 27)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//此处必须注意要穿引用,若是传值的话会出现无限递归调用
	Date1(const Date1& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};

class Date2
{
public:
	Date2(int year = 2020, int month = 3, int day = 27)
	{
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};

class String
{
public:
	String(const char* str = "zhangsan")
	{
		_str = (char*)malloc(strlen(str) + 1);
		strcpy(_str, str);
	}

	~String()
	{
		cout << "~String()" << endl;
		//free(_str);
		//_str = NULL;
	}

private:
	char* _str;
};

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

	Date2 d3;
	Date2 d4(d3);

	String s1("Hello,World!");
	String s2(s1);
	system("pause");
	return 0;
}

4、运算符重载

4.1、运算符重载的概念

C++为了增强代码的可读性,引入了运算符重载,运算符重载是具有特殊函数名的函数。
函数名称为:关键字operator后面接所需要重载的运算符符号
函数原型:返回值类型operator操作符(参数列表)

4.2、运算符重载的特征

注:
1、不能通过连接其他符号来创建新的操作符:比如operator@
2、重载操作符必须有一个类类型或者枚举类型的操作数
3、用于内置类型的操作符,其含义不能改变,例如:内置类型+,不能改变其含义
4、作为类成员的重载函数时,其形参看起来比操作数的数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参
5、. * :: sizeof ? : 不能重载

5、赋值运算符重载

5.1、赋值运算符重载概念

赋值运算符重载
1、参数类型
2、返回值
3、检测是否自己给自己赋值
4、返回*this
5、若是没有显示定义,编译器会自动生成,完成对象按字节序的值拷贝

#define _CRT_SECURE_NO_WARNINGS

#include 
#include 

using namespace std;

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

//若是operator做全局的,那么封装性不能被保证
//此处可以做出友元或者直接做成成员函数
bool operator==(const Date1& d1, const Date1& d2)
{
	return d1._year == d2._year && d1._month == d2._month && d1._day == d2._day;
}

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

	//bool operator==(Date* this, const Date& d2)
	//此处左操作数是this指向的调用函数的对象
	bool operator==(const Date2& d2)
	{
		return _year == d2._year && _month == _month && _day == _day;
	}
public:
	int _year;
	int _month;
	int _day;
};

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

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

	Date3& operator=(const Date3& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
	}
public:
	int _year;
	int _month;
	int _day;
};

class Date4
{
public:
	Date4(int year = 2020, int month = 3, int day = 28)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	bool operator==(const Date4& d2)
	{
		return _year == d2._year && _month == _month && _day == _day;
	}
public:
	int _year;
	int _month;
	int _day;
};

class String
{
public:
	String(const char* str = "")
	{
		_str = (char*)malloc(strlen(str) + 1);
		strcpy(_str, str);
	}

	~String()
	{
		cout << "~String()" << endl;
		free(_str);
	}
private:
	char* _str;
};

int main()
{
	Date1 d1(2020, 3, 27);
	Date1 d2(2020, 3, 28);
	cout << (d1 == d2) << endl;

	Date2 d3(2020, 3, 28);
	Date2 d4(2020, 3, 28);
	cout << (d3 == d4) << endl;

	Date4 d5;
	Date4 d6(2020, 3, 28);
	d5 = d6;
	cout << (d5 == d6) << endl;

	String s1("Hello");
	String s2("World");

	s1 = s2;

	system("pause");
	return 0;
}

6、const成员

6.1、const修饰的成员函数

将const修饰的类成员函数称为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明该成员函数中不能对类的任何成员进行修改

注:
1、非const对象可以调用const成员函数
2、非const成员函数可以调用其他const成员函数

#include 

using namespace std;

//const修饰的成员函数实际上修饰的是成员函数的this指针
//表面该成员函数中不能对类的任何成员进行修改

//非const对象可以调用const成员函数
//非const成员函数可以调用const成员函数
class Date
{
public:
	Date(int year = 2020, int month = 3, int day = 28)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Display()
	{
		cout << "Display()" << endl;
		cout << "year:" << _year << endl;
		cout << "month:" << _month << endl;
		cout << "day:" << _day << endl;
	}

	void Display()const
	{
		cout << "Display()const" << endl;
		cout << "year:" << _year << endl;
		cout << "month:" << _month << endl;
		cout << "day:" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;
	d1.Display();

	const Date d2;
	d2.Display();
	system("pause");
	return 0;
}

7、取地址运算符重载和const取地址运算符重载

#include 

using namespace std;

//取地址运算符重载
//const取地址运算符重载

//注:这两个运算符重载一般默认给出, 若无特殊情况,则无需重载。
class Date
{
public:
	Date* operator&()
	{
		return this;
	}

	const Date* operator&()const{
		return this;
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{

	system("pause");
	return 0;
}

你可能感兴趣的:(类的默认成员函数(构造函数,析构函数,拷贝构造函数,赋值运算符重载,取地址运算符重载,const取地址运算符重载))