c++(18)操作符重载

先看一下操作符重载的基本语法,注意在函数声明时,operator操作符重载关键字后不加空格。

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
	
class Point
{
public:
	Point()
	{
		m_X = 0;
		m_Y = 0;
	}
	
    Point(int x, int y):m_X(x),m_Y(y)
	{
	}
	
	void printPoint(void)
	{
		cout<<"["<<m_X<<","<<m_Y<<"]"<<endl;
	}
	
	//方式2:局部函数声明,通过类的成员函数实现。
	Point operator+(Point &another)
	{
		Point temp;
		temp.m_X = m_X+another.m_X;
		temp.m_Y = m_Y+another.m_Y;
		return temp;
	}
	
public:
    int m_X;
	int m_Y;
};

#if 0
//方式1:全局函数声明。在函数声明时,operator操作符重载关键字后不加空格。
Point operator+(Point &p1, Point &p2)
{
	Point temp;
	temp.m_X = p1.m_X+p2.m_X;
	temp.m_Y = p1.m_Y+p2.m_Y;
	return temp;;
}
#endif

int main(void)
{	
	Point a(1, 1);
	Point b(2, 2);
	Point c = a + b;//这句话在执行的时候,就等价于 全局:operator+(a, b)
												// 局部:a.operator+(b)
	c.printPoint();
	
	return 0;
}

关于重载的规则

(1)c++不允许用户自己定义新的运算符,只能对已有的c++运算符进行重载

(2)c++有些运算符不可重载

下面是可重载的运算符列表:

双目算术运算符+ (加),-(减),*(乘),/(除),% (取模)
关系运算符==(等于),!= (不等于),< (小于),> (大于),<=(小于等于),>=(大于等于)
逻辑运算符||(逻辑或),&&(逻辑与),!(逻辑非)
单目运算符+ (正),-(负),*(指针),&(取地址)
自增自减运算符++(自增),--(自减)
位运算符| (按位或),& (按位与),~(按位取反),^(按位异或),,<< (左移),>>(右移)
赋值运算符=, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>=
空间申请与释放new, delete, new[ ] , delete[]
其他运算符()(函数调用),->(成员访问),,(逗号),[](下标)

下面是不可重载的运算符列表:

  • .:成员访问运算符
  • .*, ->*:成员指针访问运算符,取值操作符
  • :::域运算符
  • sizeof:长度运算符
  • ?::条件运算符
  • #: 预处理符号

(3)运算符重载不能改变运算符对象(即操作数)的个数

(4)重载不能改变运算符的优先级别

(5)重载不能改变运算符的结合性

(6)重载运算符的函数不能有默认参数

(7)重载的运算符,必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。

重载前++ 

下面额外补充一个左移右移操作符的重载

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
	
class Point
{
public:
	Point()
	{
		m_X = 0;
		m_Y = 0;
	}
	
    Point(int x, int y):m_X(x),m_Y(y)
	{
	}
	
	void printPoint(void)
	{
		cout<<"["<<m_X<<","<<m_Y<<"]"<<endl;
	}
	
	#if 0
	//这样调用的话,左边的参数必须是对象
	//Point A;
	//A<<cout;
	ostream & operator<<(ostream &os)
	{
		os<<"["<<m_X<<","<<m_Y<<"]"<<endl;
		return os;
	}
	#endif
	
public:
    int m_X;
	int m_Y;
};

#if 1
//注意左移右移操作符不建议作为类的成员函数重载定义,否则会出现逻辑使用偏差
ostream & operator<<(ostream &os, Point &p)
{
	os<<"["<<p.m_X<<","<<p.m_Y<<"]"<<endl;
	return os;
}

istream & operator>>(istream &is, Point &p)
{
	cout<<"x:";
	is>>p.m_X;
	cout<<"y:";
	is>>p.m_Y;
	
	return is;
}
#endif

int main(void)
{	
	Point a(1, 1);
	Point b(2, 2);
	
	cin >> a;
	cin >> b; //相当于调用operator>>(cin, b)
	
	cout << a << b;	//相当于调用operator<<(cout, a),返回os,然后再调用operator<<(cout, b)
	
	return 0;
}

运行结果

等号操作符重载,深拷贝操作

#include <iostream>
#include <cstring>
using namespace std;

class teacher
{
public:
    teacher(int id, const char *name)
	{
		cout<<"teacher(int id, const char *name) ...."<<endl;
		m_id = id;
		m_name = new char[strlen(name)];
		if (NULL != m_name)
		{
			strcpy(m_name, name);
		}
	}
	
	~teacher()
	{
		cout<<"~teacher() ...."<<endl;
		if (NULL != m_name)
		{
			delete m_name;
		}
	}
	
	void Pinrt()
	{
		cout<<"id="<<m_id<<", name="<<m_name<<endl;
	}
	
	teacher(const teacher &another)
	{
		m_id = another.m_id;
		m_name = new char[strlen(another.m_name)];
		if (NULL != m_name)
		{
			strcpy(m_name, another.m_name);
		}
	}
	
	teacher &operator=(const teacher &another)
	{
		if (this == &another)
		{
			return *this;
		}
		
		if (this->m_name != NULL)
		{
			delete this->m_name;
			this->m_name = NULL;
			this->m_id = 0;
		}
		
		//深拷贝动作
		this->m_id = another.m_id;
		this->m_name = new char[strlen(another.m_name)];
		if (NULL != this->m_name)
		{
			strcpy(this->m_name, another.m_name);
		}
		
		return *this;
	}
#if 0
	//默认拷贝构造的实现
	teacher(const teacher &another)
	{
		m_id = another.m_id;
		m_name = another.m_name;
	}
#endif
	
private:
    int m_id;
	char *m_name;
};

int main(void)
{
	teacher t1(10, "zhang3");
	t1.Pinrt();
	
	teacher t2(20, "li4");
	t2 = t1;  //如果没有重载=运算符,执行的是默认的=赋值,是浅拷贝,将zhang3的地址直接赋值给t2的m_name,析构的时候报错。
	t2.Pinrt();
	
	teacher t3(30, "wang5");
	//也可以实现连等操作
	t2 = t1 = t3;
	t2.Pinrt();
	return 0;
}

注意代码中的注释和理解,堆上的空间时如何申请和释放的。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值