C++:重载运算符

写在前面

运算符重载在学的时候着实把我绕进去了,他的实质是用常规运算符实现特殊数据类型的计算。

int a = 10 , b = 20;
int c = a + b;

+可以实现a和b的相加

class Person
{
	……
}
Person a , b;
Person c = a + b;

但如果是Person类型 他们还能相加吗
显然编译器不知道 所以我们需要用到重载运算符 让编译器按照我们的方式计算

重载加号运算符

假如我们有一个类

class MyInteger
{
public:
	MyInteger(int a, int b)
	{
		this->m_A = a;
		this->m_B = b;
	}
private:
	int m_A , m_B;
};
int main()
{
	Person a(1 , 2);
	Person b(3 , 4);
	Person c = a + b;
}

我们希望 a和 b 相加 是 其中成员m_A 和 m_B相加
咋办呢

全局函数重载

MyInteger operator+ (const Person& p1 , const Person& p2)
{
	MyInterger temp;
	temp.m_A = p1.m_A + p2.m_A;
	temp.m_B = p1.m_B + p2.m_B;
	return temp;
}

调用时是这样的

operator+(p1 , p2);

可以简写成

p1 + p2;

这就是重载运算符的好处

由于调用了private成员 我们还要在类里声明

friend MyInteger operator+ (const Person& p1 , const Person& p2);

成员函数里重载

在类中重载其实是一个对象调用成员函数

Person operator+ (const Person& p)
	{
		Person temp;
		temp.m_a = this->m_a + p.m_a;
		temp.m_b = this->m_b + p.m_b;
		return temp;
	}

调用时

p1.operator+(p2);

简写成

p1 + p2;

注意的地方

返回值一定是 类 的类型 否则试试这个

MyInteger p = p1 + p2 + p3;

重载<<

最让我头疼的地方

理解cout

cout 是 ostream 类的一个对象,全局只能有一个
我们平常所用的 cout << 都是经过重载的
比如

cout << 233;

operator<<(cout , 233);

的简写

所以我们可以找葫芦画瓢

(返回值先不写) operator<< (ostream& output , const MyInteger& p)
{
	output << p.m_A << " " << p.m_B << endl;
	return (……);
}

这个时候我们就可以输出

MyInteger p1(10 , 20) , p2(30 , 40);
operator<<(cout , p1);

简写成

cout << p1;

但是 如果是这样 代码还能运行吗 不能了

cout << p1 << p2;

上面这行代码实质是这样的

operator<<(operator<<(cout , p1) , p2);

所以刚才的返回值我们就知道怎么写了

ostream& operator<< (ostream& output , const MyInteger& p)
{
	output << p.m_A << " " << p.m_B << endl;
	return output;
}

思考

<< 不能用成员函数重载 想一下为什么

因为重载后是 成员.operator<<(cout) , cout 不能放左边

重载递增

实现 a ++ , ++ a等操作
a++是先用a的值作为表达式的值 再让a增加
++a是先让a增加然后作为表达式的值

MyInteger& operator++() //前置重载 返回引用是为了一直对一个数操作
	{
		m_Integer++;
		return *this;
	}

为什么返回MyInteger型
因为 ++ ++a;链式类型

不过这样重载无论你的++放前面还是后面编译器都会认为是 ++a

如果真的想实现a++ 就在重载函数里加上一个占位数(只能为int) 编译器就会认为这是后置地址 不过无法实现链式编程 想想为什么

MyInteger operator++(int) //区分前后置使用占位参数 加上编译器认为是后置递增
	{
		MyInteger temp = *this;
		m_Integer ++;//先记录当时结果
		return temp; //不能返回引用 无法实现链式编程
	}

重载关系运算符

我们比较时经常用== != 这两个同样不能用于特殊类型
重载方式与加减类似

全局

bool operator==(Person a , Person b)
{
    if (a.m_a == b.m_a && a.m_b == b.m_b)
        return 1;
    return 0;
}

不要忘了在类内声明

friend bool operator==(Person a , Person b);

调用

	Person p1(10 , 20);
    Person p2(10 , 20);

    if (p1 == p2) //返回bool类型
    {
        cout << "p1 和 p2 相等" << endl;
    }

重载赋值运算符

有涉及到了浅拷贝和深拷贝的问题
假如类里涉及到了堆区操作
编译器赋值只是浅拷贝 我们必须重载运算符让其变成深拷贝

class Person
{
public:
	Person (int age)
	{
		m_age = new int (age);
	}

	int* m_age;
	//重载赋值运算符
	Person& operator=(Person& p)
	{
		//编译器提供的浅拷贝
		//this->m_age = p.m_age
		//先判断是否有属性在堆区
		if (this->m_age != NULL)
		{
			delete this->m_age;
			this->m_age = NULL;
		}

		this->m_age = new int(*p.m_age);
		return *this;
	}
};

返回Person 类型是因为C++支持连续赋值

a = b = c;

重载括号

我们可以重载括号让其使用的时候有特殊操作

class MyPrint
{
public:
	//重载函数调用运算符
	void operator()(string test)
	{
		cout << test;
	}
};
void test01()
{
	MyPrint myprint;
	myprint("helloworld"); //由于使用起来非常想函数调用
	//成为仿函数
}

使用起来非常像函数调用 所以叫仿函数
仿函数 括号前面是对象

//加法类
class MyAdd
{
public:
	int operator()(int a , int b)
	{
		return a + b;
	}
};
void test02()
{
	MyAdd a;
	int ret = a(100 , 200);
	cout << ret;
}

总结

在全局函数重载时

一般类型是 返回类型 operator运算符(变量1,变量2)
一般调用为 operator运算符(变量1,变量2)
一般简写为 变量1 运算符 变量2

在成员函数重载时

一般类型为 返回类型 operator运算符(变量)
一般调用为 对象.operator运算符(变量)
一般简写为 对象 运算符 变量

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值