c++类和对象(2)

运算符重载

c++中在自定义类型进行比较时给了运算符重载这个概念
让自定义类型可以进行运算符操作
在类中 定义运算符重载: operator + 符号
拿年月日这个类来说

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
	//因为在类中 函数中有一个this 隐藏的变量
	bool operator>(const Date& y)
	{
		if (_year > y._year)
		{
			return true;
		}
		else if (_year == y._year && _month > y._month)
		{
			return true;
		}
		else if (_year == y._year && _month == y._month && _day > y._day)
		{
			return true;
		}
		return false;
	}

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

	/*int operator-(const Date& d)
	{

	}*/

	int GetMonthDay(int year, int month)
	{
		static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,31 };
		int day = days[month];
		if (month == 2
			&& ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
		{
			day += 1;
		}
		return day;
	}


	Date& operator+=(int day)
	{
		_day += day;
		while (_day > GetMonthDay(_year, _month))//判断_day 是否大于当月的天数 如果大于 月++
		{
			_month++;
			_day -= GetMonthDay(_year, _month);
			if (_month > 12)
			{
				_year++;
				_month -= 12;
			}
		}
		return  *this;
	}

	Date operator+(int day)
	{
		Date tmp(*this);
		tmp += day;//用tmp来接收 this传的类 调用+= 之后类不变  

		return tmp;
	}

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

因为类中是有隐藏的 this , 所以 只用传一个对象

运算符中的前置++和后置++/前置–和后置–

因为前置++是先++后使用,所以要传改变的值回去

Date& Date::operator++()//前置++
{
	*this += 1;
	return *this;
}

后置++是先使用后++,所有要用一个对象来接受然后传对象,但是本身传的对象是进行了改变的,并且为了和前置++区分,c++规定了,要在传值的时候传一个空的值

//后置++ 因为要构成重载 所有函数内要 int
//特殊处理
Date Date::operator++(int)
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}

前置–和后置–与++相同

Date& Date::operator--()
{
	*this -= 1;
	return *this;
}
Date Date::operator--(int)
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}

特殊运算符 <<(流插入) / >>(流提取)

因为这两个比较特殊 要有单独的规定
流插入本身只能插入内置类型 ,我们要单独在全局里面重载一个插入

ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "/" << d._month << "/" << d._day << endl;
	return out;
}

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

ostream 是一个类 cout是这个类的对象 所以要调用这个类才能进行流插入
istream 是一个类 cin是这个类的对象 所有要调用这个类才能进行流提取
返回是返回对应的流入的对象是因为 可以二次插入/提取

为什么是定义全局的<< / >>

因为如果是在类里面 ,类里面的成员函数都会 有一个隐藏的 this 他占据
函数传参的第一个位置 所以 如果在类里面写流插入 / 流提取的话
那么他最后只能
对象<< cout 这样子插入
对象>> cin 这样子提取
可读性很差所以

全局怎么调用类里面的私有?

友元函数: friend +函数声明 叫友元函数 友元函数可以访问类里面的私有

const定义对象

如果const 定义一个变量时 类里面的成员函数不能使用
为了避免这个问题 c++推出了 在类里面的函数 中 需要 用到 const 定义的对象 使用成员函数的方法 , 在成员函数 后面加 const
需要有修改的函数 不用加 const

#include"Date.h"

Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
	if (_year < 1 || _month < 1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month))
	{
		//perror("日期非法");
		cout << "日期非法" << endl;
		exit(-1);
	}
}


int GetMonthDay(int year, int month)
{
	static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,31 };
	int day = days[month];
	if (month == 2
		&& ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
	{
		day += 1;
	}
	return day;
}


Date& Date::operator=(const Date& d)
{
	//避免自己给自己赋值
	if (this != &d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	return *this;
}

Date& Date::operator+=(int day)
{
	if (day < 0)
	{
		return *this -= (-day);
	}
	_day += day;
	while (_day > GetMonthDay(_year, _month))//判断_day 是否大于当月的天数 如果大于 月++
	{
		_month++;
		_day -= GetMonthDay(_year, _month);
		if (_month > 12)
		{
			_year++;
			_month -= 12;
		}
	}
	return  *this;
}

Date& Date::operator-=(int day)
{
	if (day < 0)
	{
		return *this += (-day);
	}
	_day -= day;
	while (_day <= 0)
	{
		_month--;
		if (_month <= 0)
		{
			_month += 12;
			_year--;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

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

bool Date::operator>(const Date & y) const
{
	return !(*this <= y);	
	/*if (_year > y._year)
	{
		return true;
	}
	else if (_year == y._year && _month > y._month)
	{
		return true;
	}
	else if (_year == y._year && _month == y._month && _day > y._day)
	{
		return true;
	}
	return false;*/
}

bool Date::operator<(const Date& y) const
{
	return !(*this >= y);

	/*if (_year < y._year)
	{
		return true;
	}
	else if (_year == y._year && _month < y._month)
	{
		return true;
	}
	else if (_year == y._year && _month == y._month && _day < y._day)
	{
		return true;
	}
	return false;*/
}

bool Date::operator<=(const Date& y) const
{
	if (_year <= y._year)
	{
		return true;
	}
	else if (_year == y._year && _month <= y._month)
	{
		return true;
	}
	else if (_year == y._year && _month == y._month && _day <= y._day)
	{
		return true;
	}
	return false;
}
bool Date::operator>=(const Date& y) const
{
	if (_year >= y._year)
	{
		return true;
	}
	else if (_year == y._year && _month >= y._month)
	{
		return true;
	}
	else if (_year == y._year && _month == y._month && _day >= y._day)
	{
		return true;
	}
	return false;
}

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

Date Date::operator+(int day)
{
	Date tmp(*this);
	tmp += day;//用tmp来接收 this传的类 调用+= 之后类不变  

	return tmp;
}

Date Date::operator-(int day)
{
	Date tmp(*this);
	tmp -= day;
	return tmp;
}

int Date::operator-(const Date& d)
{
	int flag = 1;
	Date max = *this;
	Date min = d;
	if (*this < d)
	{
		max = d;
		min = *this;
		flag = -flag;
	}
	int n = 0;
	while (max != min)
	{
		++n;
		++min;
	}
	return n * flag;
}

Date& Date::operator++()//前置++
{
	*this += 1;
	return *this;
}
//后置++ 因为要构成重载 所有函数内要 int
//特殊处理
Date Date::operator++(int)
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}

Date& Date::operator--()
{
	*this -= 1;
	return *this;
}
Date Date::operator--(int)
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}

ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "/" << d._month << "/" << d._day << endl;
	return out;
}

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

构造函数的补充

构造函数里面 可以在函数内初始化,也可以在函数外进行初始化
为什么要有函数外初始化呢?
c++中的引用、const 成员变量、 类 无法在函数内初始化
初始化外 叫初始化列表
: 开头 ,换行
函数内外可以同时使用
有些检查的要在函数体内
尽量使用初始化列表

struct A
{
public:
    A(int a)
        :_a(a)
    {

    }
private:
    int _a;
};

class Date
{
public:
    Date(int year, int month, int day)
        //初始化列表
        //尽量使用初始化列表
        //构造函数不能只要初始化列表还要函数体内
        //有些检查的要在函数体内
        //:开始 ,换行
        //列表和函数内可以混着用
        //但是 引用 和 const 必须在列表定义
        :_m(year)
        , _n(1)
        , _aa(10)
    {
        //函数体内初始化
        //剩下的这三个成员没有在初始化列表中显示写出来定义
        //但是他也会定义,只是内置类型他会给随机值
        //如果是自定义类型他会调用自己的默认构造函数
        _year = year;
        _month = month;
        _day = day;
    }
private:
    //初始化是按声明走的
    int _year;
    int _month;
    int _day;
    //引用 是无法在构造函数内初始化
    int& _m;
    //const 也无法在构造函数内初始化
    const int _n;
   
    A _aa;
};
  • 19
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dabai__a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值