【C++】二 、类和对象总结

== 1.类的6个默认成员函数==

1.1 构造函数主要完成初始化工作
1.2 析构函数主要完成清理工作
1.3 拷贝构造是使用同类对象初始化创建对象
1.4 赋值重载主要是把一个对象赋值给另一个对象
1.5 普通对象取地址
1.6 const对象取地址
1.7.static成员

== 2.构造函数==

1.构造函数是特殊的成员函数,构造函数的主任务并不是开辟空间创建对象,而是对象的初始化。
其特征如下:
1.函数名与类名相同。
2.无返回值。
3.对象实力化时编译器自动调用对应的构造函数
4.构造函数可以重载



class  /* 定义类的关键字*/  Date  //类的名字
{   //  { }中为类的主体  
    //类体:由成员变量和成员函数组成
	//类中的数据称为类的属性或者成员变量。
	//类中的函数称为类的方法或者成员函数。
	//	声明和定义最好不要都放在类体中 声明在.h中 定义在.cpp中
public:
	void Display()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

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

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


};
int main()
{
	Date d1, d2;
	d1.SetDate(2012,12,12);
	d2.SetDate(2012,11,10);
	d1.Display();
	d2.Display();
	return 0;
}

5.如果·类没有显示定义构造函数,则C++编译器会自动生成一个无参数的默认构造函数,一旦用户显示定义将不再生成



class   Date 
{   
public:

private:
	int _year;
	int _month;
	int _day;
};
void Test ()
{
	Date d;
	
}

6.无参函数和全缺省函数都称为默认函数,并且只能有一个
当然定义的时候最好使用全缺省函数



class  /* 定义类的关键字*/  Date  //类的名字
{   //  { }中为类的主体  
    //类体:由成员变量和成员函数组成
	//类中的数据称为类的属性或者成员变量。
	//类中的函数称为类的方法或者成员函数。
	//	声明和定义最好不要都放在类体中 声明在.h中 定义在.cpp中
public:
	Date(int year = 1, int month = 1 , int day= 1//常用的写法
	{
		_year = year;
		_month= month;
		_day = day;

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


};
void test()
{
  Date d1;
}

7.初始化列表
类和对象有两种初始化方式
1.函数体内赋值初始化
2.初始化列表



class Date
{
public:
	Date(int year = 1, int mouth = 1, int day = 1)
	{
	//函数体内初始化
		_year = year;
		_mouth = mouth;
		_day = day;
	}
	Date(int year = 1, int mouth = 1, int day = 1)_year(year)
		,_month(month)
		,_day(day)
		
	{
	 //初始化列表
		
	}
private:
	int _year;
	int _month;
	int _day;
};


1.每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
2.类中包含以下成员,必须放在初始化列表位置进行初始化:
== 引用成员变量==
== const成员变量==
自定义类型成员(该类没有默认构造函数)



class A
{
public:
//初始化列表是成员函数定义的地方
		A(int a)
			:_a(a)
		{}
private:
			int _a;
};

class B
{
public:
		B(int a, int ref)
			:_aobj(a)
			,_ref(ref)
			,_n(10)
		{}
private:  //因为他们都必须在定义的时候初始化,而初始化列表是成员变量定义的位置。
			A _aobj;        //没有默认构造函数
			int& _ref;	     // 引 用
			const int _n; // const
};			

3.尽量使用初始化列表初始化,会更加高效。因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使 用初始化列表初始化。



class Time
{
public:
			Time(int hour = 0)
				:_hour(hour)
			{
				cout << "Time()" << endl;
			}
private:
				int _hour;
};
class Date
{
public:
			Date(int day)
			{}

private:
				int _day; Time _t;
};

int main()
{
			Date d(1);
}

4.成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关

== 3.析构函数==

其特征如下:
1.析构函数名是在类名前加上字符 ~。
2.无参数无返回值。
3.一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
4.对象生命周期结束时,C++编译系统系统自动调用析构函数。



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



    ~Date()	//析构函数 (一般清理 动态资源)
    				//1.无参数 无返回值
	{      			//2.一个类有且只有一个析构函数。若未显示定义
		            //系统会自动生成默认的析构函数
					//3.对象生命周期结束时,C++编译系统自动调用析构函数
					//4.Date类没有资源需要清理,所以析构函数类什么都不用写

	}
	private:
	
};

还有先构造的后析构哦
在这里插入图片描述

== 4.拷贝构造函数==

其特征如下:
1.拷贝构造函数是构造函数的一个重载形式。
2.拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。(如图)
3.若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝我们叫做浅拷贝,或者值拷贝。
在这里插入图片描述



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

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

& 千万不要忘记
在这里插入图片描述

== 5.赋值运算符重载==

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
1.不能通过连接其他符号来创建新的操作符:比如operator@
2.重载操作符必须有一个类类型或者枚举类型的操作数

3.用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参
4.(.*) 、:: 、sizeof 、?: 、(. )注意以上5个运算符不能重载。

赋值运算符主要有四点:

1.参数类型
2.返回值
3.检测是否自己给自己赋值
4.返回*this
5.一个类如果没有显式定义赋值运算符重载,编译器也会生成一个,完成对象按字节序的值拷贝。
应用:日期类的实现



#include<iostream>
using namespace std;

class Date
{

public:
	int GetMonthDays(int year, int month)
	{
		int MonthDays[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
			if (month == 2 
				&&((year % 4 == 0 && year % 100 != 0 )||year % 400 == 0) )
		{
			return 29;

		}
			else
			{
				return MonthDays[month];
			}

	}

	Date (int year = 0, int month = 1, int day = 1)
	{

		if (year >= 0
			&& month > 0 && month < 13
			&& day > 0 && day <= GetMonthDays(year, month))

		{
			_year = year;
			_month = month;
			_day = day;


		}

		else
		{
			cout << "非法日期" << endl;
		}



	}
	Date(const Date& d)
	{

		_year = d._year;
		_month = d._month;
		_day = d._day;

		cout << "调用我啦" << endl;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}




	//d1 = d3 d3赋值给d1 d1.operator=(&d1,d3)
	//Date& operator = (const Date &d)//d1传给隐含的this d3传给d
	//	//建议传引用 提高效率
	//	//建议加const进行保护
	//{
	//	if (this != &d)
	//	{
	//		this->_year = d._year;
	//		this->_month = d._month;
	//		this->_day = d._day;
	//	}
	//	return *this;
	//}



	//  1.日期 += 天数
	//d1+100天  d1.operator+(&d1 , 100);
	Date operator+=(int day)  //另一个是隐含的
	{
		_day += day;
		while (_day > GetMonthDays(_year ,_month))
		{
			//减掉当期月的天数
			_day -= GetMonthDays(_year, _month);
			++_month;//月进1
			if (_month == 13)
			{
				_year++;//月满了 年进1
				_month = 1;//月置1

			}
		}
		return *this; //也可以用引用返回
	}
	//2.日期 + 天数 不能改变日期
	Date operator+(int day)
	{
		/*Date ret(*this); // 不改变的d1 所以创建一个临时对象
		//ret 就是拷贝构造出来的d1   ret是可以改变的 *this就是d1
		ret._day += day;
		while (ret._day > GetMonthDays(ret._year, ret._month))
		{
			ret._day -= GetMonthDays(ret._year, ret._month);
			++ret._month;//月进1
			if (ret._month == 13)
			{
				ret._year++;//月满了 年进1
				ret._month = 1;//月置1
			}

		}*/
		Date ret(*this);
			 ret += day;
			return ret;//返回临时对象
	}


	// 3.日期 -= 天数
	Date operator -= (int day)
	{
		if (day < 0)
		{
			day = -day;
			return *this;

		}
		_day -= day;
		while (_day <= 0)//=0表示 0天的时候也会退回上一个月
		{
			--_month;
			if (_month == 0)
			{
				--_year;
				_month = 12;
			}
			_day += GetMonthDays(_year, _month);
			
		}
		
		return *this;

	}






	// 4.日期  - 天数
	Date operator - (int day)
	{
		Date ret(*this);
		ret -= day;
		return ret;
	}

	//5.  ++前置
	//d1.operator++(&d1)
	Date& operator++ ()
	{
		*this += 1;
		return *this;
	}
	//6. 后置++   返回++之前的值
	//d1.operator++(&d1 , 0)
	Date operator++ (int i) //为了区分与前置++ 这里加一个参数
	{
		//返回++之前的值
		Date ret(*this);//把++之前的值拷贝构造保存起来
		*this += 1;
		return ret;//出了作用域返回值就不存在了 不能用引用返回

	}




	/*bool operator*/

		 
	//7. d1 < d2
	bool operator < (const Date& d)
	{
		if ((_year < d._year)
			|| (_year == d._year && _month < d._month)
			|| (_year == d._year && _month == d._month && _day < d._day))
		{
			return true;
		}
		return false;
		
	}

	//8.d1 > d2
	bool operator > (const Date& d)
	{
		if ((_year > d._year)
			|| (_year == d._year && _month > d._month)
			|| (_year == d._year && _month == d._month && _day > d._day))
		{
			return true;
		}
		return false;

	}
	//d1  ==   d2   //如果Date加了 时-分-秒 成员 下面的改动最小
	bool operator == (const Date& d)
	{
		return _year == d._year && _month == d._month && _day == d._day;
	}


	//9.d1 <= d2
	bool operator <= (const Date& d)
	{
		return *this < d || *this == d ;

	}

	//10. d1 >= d2
	bool operator >= (const Date& d)
	{
		return !(*this < d);

	}





	
	//11.d1 != d2
	bool operator != (const Date& d)
	{
		return !(*this == d);

	}




	//12. 日期 - 日期
	int operator - (const Date& d)
	{
		int flag = -1;
		 Date min = *this;
		 Date max = d;
		 if (*this > d)
		 {
			 flag = 1;
			 min = d;
			 max = *this;
		 }
		 int n = 0;
		 while (min != max)
		 {
			 ++n ;
			 ++min ;
		 }

		 return n*flag ;
	}


 private:
	
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2012, 3,19);
	d1.Print();
	Date d2(2020, 4, 20);
		d2.Print();
	//Date d3 = d1 - 19; // 不改变原值
	//d1.Print();
	//d3.Print();



	//Date d2 = d1 -= 19;//改变原值
	//d1.Print();
	//d2.Print();
	/*Date d2(d1);
	d2.Print();



	Date d4 = d1++;
	d1.Print();
	d4.Print();
	Date d5 = ++d2;
	d2.Print();
	d5.Print();*/

		Date d6 = d2 - d1;
	/*	d6.Print();*/
		cout << d1 - d2 << endl;
   /*日期+天数  运算符重载
	日期-天数
	日期+=天数
	日期-=天数
	日期-日期*/

	return 0;
}

日期 += 天数 日期+天数
在这里插入图片描述
日期-=天数 日期-天数
在这里插入图片描述

前置++ 后置++
在这里插入图片描述

== 6.成员函数const==

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

== 7.static成员==

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的 成员函数,称之为静态成员函数。静态的成员变量一定要在类外进行初始化
实现一个类,计算中程序中创建出了多少个类对象。



class A
{
public:
		A() 
		{
		++n;
		}
		A(const A& t) 
		{
		++n;
		}
		Get N()
		{
		return n;
		}

private:
		static int n  ;

}int A :: int n = 0 ;//为什么不在构造函数初始化,因为n不是属于某个对象,n属于这个类,
//与属于这个类的所有对象

void f (A a)
{
}


int main()
{
		A a1;
		A a2;
		A a3(a2);
		f(a1);
		cout<< n << endl;
		return 0 ; 
}

1.静态成员为所有类对象所共享,不属于某个具体的实例
2.静态成员变量必须在类外定义,定义时不添加static关键字
3.类静态成员即可用类名::静态成员或者对象.静态成员来访问
4.静态成员函数没有隐藏的this指针,不能访问任何非静态成员
5.静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值