c++--类和对象operator成员函数

文章详细介绍了C++中的运算符重载,包括全局和类内赋值运算符重载规则,以及前置和后置自增自减运算符的特殊处理。还展示了如何在Date类中实现各种运算符,以及保证封装性的方法。
摘要由CSDN通过智能技术生成

一operator,运算符的重载

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

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐 藏的this
  • .* :: sizeof ?: . 注意以上5个运算符不能重载。这个经常在笔试选择题中出 现。

1运算符的重载

// 全局的operator==
class Date
{ 
public:
 Date(int year = 1900, int month = 1, int day = 1)
   {
        _year = year;
        _month = month;
        _day = day;
   }    
//private:
 int _year;
 int _month;
 int _day;
};
// 这里会发现运算符重载成全局的就需要成员变量是公有的,那么问题来了,封装性如何保证?
// 这里其实可以用我们后面学习的友元解决,或者干脆重载成成员函数。
bool operator==(const Date& d1, const Date& d2)
{
    return d1._year == d2._year
   && d1._month == d2._month
        && d1._day == d2._day;
}

class Date
{ 
public:
 Date(int year = 1900, int month = 1, int day = 1)
 {
        _year = year;
        _month = month;
        _day = day;
   }
    
    // bool operator==(Date* this, const Date& d2)
    // 这里需要注意的是,左操作数是this,指向调用函数的对象
    bool operator==(const Date& d2)
 {
        return _year == d2._year;
            && _month == d2._month
            && _day == d2._day;
 }
private:
 int _year;
 int _month;
 int _day;
};
void Test ()
{
    Date d1(2018, 9, 26);
    Date d2(2018, 9, 27);
    cout<<(d1 == d2)<<endl;
}

上面是两种方式

  • 代码一是在全局上定义bool operator==(const Date&d1,const Date &d2) 较为方便
  • 代码二是在类里面定义运算符函数,所以有一个隐含的this指针在前面,在Test的测试中this代表了d1的形参

 

2赋值运算符的重载

2.1赋值运算符重载格式

  • 参数类型:const T&,传递引用可以提高传参效率 返回值类型:T&,
  • 返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
  • 检测是否自己给自己赋值
  • 返回*this :要复合连续赋值的含义

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;
   }
 
 Date& operator=(const Date& d)
 {
 if(this != &d)
       {
            _year = d._year;
            _month = d._month;
            _day = d._day;
       }
        
        return *this;
 }
private:

 int _year ;
 int _month ;
 int _day ;
};

2.2 赋值运算符只能重载成类的成员函数不能重载成全局函数

class Date
{
public:
 Date(int year = 1900, int month = 1, int day = 1)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 int _year;
 int _month;
 int _day;
};
// 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
Date& operator=(Date& left, const Date& right)
{
 if (&left != &right)
 {
 left._year = right._year;
 left._month = right._month;
 left._day = right._day;
 }
 return left;
}

原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现 一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值 运算符重载只能是类的成员函数。 

2.3. 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝

注 意:内置类型成员变量是直接赋值的,

而自定义类型成员变量需要调用对应类的赋值运算符 重载完成赋值。

typedef int DataType;
class Stack
{
public:
 Stack(size_t capacity = 10)
 {
 _array = (DataType*)malloc(capacity * sizeof(DataType));
 if (nullptr == _array)
 {
 perror("malloc申请空间失败");
 return;
 }


 _size = 0;
 _capacity = capacity;
 }
 void Push(const DataType& data)
 {
 // CheckCapacity();
 _array[_size] = data;
 _size++;
 }
 ~Stack()
 {
 if (_array)
 {
 free(_array);
 _array = nullptr;
 _capacity = 0;
 _size = 0;
 }
 }
private:
 DataType *_array;
 size_t _size;
 size_t _capacity;
};
int main()
{
 Stack s1;
 s1.Push(1);
 s1.Push(2);
 s1.Push(3);
 s1.Push(4);
 Stack s2;
 s2 = s1;
 return 0;
}

注意:如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必
须要实现。具体原因涉及深拷贝和浅拷贝,会free两次空间,看

3前置++,后置++

前置++Date &operator++()

后置++Date&operaotr++(int)是固定格式,在c++中是需要记住的

class Date
{
public:
 Date(int year = 1900, int month = 1, int day = 1)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 // 前置++:返回+1之后的结果
 // 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率
 Date& operator++()
 {
 _day += 1;
 return *this;
 }
 // 后置++:
 // 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载
 // C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器
自动传递
 // 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存
一份,然后给this+1
 //       而temp是临时对象,因此只能以值的方式返回,不能返回引用
 Date operator++(int)
 {
 Date temp(*this);
 _day += 1;
 return temp;
 }
private:
 int _year;
 int _month;
 int _day;
};

二日期类的实现

#pragma once
#include<iostream>
using namespace std;
#include<assert.h>
class Date {
public:
	Date(int year = 1900, int month = 1, int day = 1);
	void printf();
	bool operator<(const Date& d);
	bool operator>(const Date& d);
	bool operator<=(const Date& d);
	bool operator>=(const Date& d);
	bool operator==(const Date& d);
	Date operator+=(int day);
	Date operator-(int day);
	bool operator!=(const Date& d);
	//前置
	Date &operator++();
	//后置特殊处理
	Date operator++(int);
	Date& operator--();
	Date operator--(int);
	Date operator-=(int  day);
	Date operator+(int day);
	int operator-(const Date& d);

	void operator<<(ostream& out);

	int getday(int year, int month)//  
	{
		static  int monthday[13] = {
			-1,31,29,31,30,31,30,31,31,30,31,30,31
		};
		if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
		{
			return 29;
		}
		return monthday[month];
	}
private:int _year;
	   int _month;
	   int _day;
};

#include"Date.h"

Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}
void Date::printf()
{
	cout << _year << " " << _month << " " << _day << endl;
}
bool Date::operator<(const Date& d)
	
{	if (d._year > _year)
	{

		return true;


	}
	else if (d._year == _year)
	{

		if (d._month == _month)
		{
			if (d._day > _day)
			{
				return true;

			}


		}
		else if (d._month >_month)
		{
			return true;
		}

	}
	return false;

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

bool Date::operator==(const Date& d)
{
	return d._year == _year && d._month ==_month && d._day == _day;
}
bool Date ::operator<=(const Date& d)
{
	return *this <d||*this==d;


}
bool Date::operator>(const Date& d)
{

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


	return !(*this < d);
}
Date Date::operator+=(int day)
{
	if (day < 0)
	{
		return *this -=-day;
	}
	_day += day;
 	while (_day >getday(_year, _month))
	{
		_day -= getday(_year, _month);
		_month++;
		if (_month > 12)
		{
			_year++;
			_month = 1;
		}

	}
	return *this;



}
//先减所有天数,再将前一个月(和加法不同)的天数抵消,其中有月尾0的情况


Date Date::operator-=(int day)
{
	_day -= day;
	while (_day <=0)
	{
		_month--;
		if (_month<1)
		{
			_year--;
			_month = 12;
		}
		_day += getday(_year, _month);

	}
	return *this;

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

}
Date Date:: operator+(int day)
{
	Date tem = *this;
	tem += day;
	return tem;
}



Date& Date:: operator++()
{
	*this += 1;
	return *this;


 }
Date Date :: operator++(int )//定义
{
	Date tem(*this);
	*this+=1;
	return tem;

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



}
Date Date:: operator--(int)
{
	Date tem(*this);
	tem -= 1;
	return tem;
}
int Date ::operator-(const Date& d)
{

	Date min = d;
	Date max = *this;
	int flag = 1;
	if (*this<d)
	{
		min = *this;
		max = d;
		flag = -1;
	}
	int day = 0;
	while (min!=max)
	{
		++min;
		day++;
	}
	return day*flag;
}

void Date:: operator<<(ostream& out)
{
	out << _year << "年" << _month << "月" << _day << "日" << endl;


}

创作不易希望支持!!!

  • 54
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 44
    评论
评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值