C++之重载操作符

概念

1.C++提供的运算符,通常只支持对于基本数据类型和标准库中提供的类进行操作,对于自定义类型如果想通过操作符实现对应的操作,需要自定义重载的操作符并实现具体的功能。
2.重载操作符:也称为重载运算符,本质上是一个函数,而且是一种特殊的重载操作符函数,并告诉 C++编译器,当遇到该运算符时就调用此函数来行使运算符功能,其本质是通过函数扩展了操作符的功能。重载操作符函数需要使用关键字operator作为函数名的一部分,重载操作符一般要有返回值,方便继续和其他操作符去操作。
3.可分两类:类内重载、类外重载。

 类内重载操作符

在类内重载,作为类成员函数,需要用对象调用,使用场景需要与函数的参数一致(包括类型和顺序)。注意在类内重载的操作符函数有隐藏的this指针作为第一个参数。在使用是要注意重载操作符的参数类型和顺序,可以直接使用操作符,也可以显示通过对象调用重载的操作符。

#include<iostream>
using namespace std;
class CTest {
public:
	int m_a;
	CTest() :m_a(1) {
		this->m_a = m_a;
	}
	int add(int a) {
		return this->m_a + a;
	}
	int operator+(/*CTest * const this*/int a) {
		return this->m_a + a;
	}

	int operator+=(int a) {
		return m_a += a;
	}
};
int main() {
	CTest tst;
	int a = tst + 20;
	int b = tst.operator+(20);
	int c = tst += 20;
	cout << a << "  " << b <<"  "<<c << "  " << tst.add(20) << endl;
	//int d = 20 + tst;  //error
	return 0;
}

输出结果: 

对于单目运算符++,有左++ 和右++ 两种,为了区分右++,我们需要额外指定一个int类型的参数,这个参数只是用来区分,并无实际意义。

#include<iostream>
using namespace std;
class CTest {
public:
	int m_a=10;
	//左++
	int operator++() {
		return ++this->m_a;
	}
	//右++
	int operator++(int a) {
		return this->m_a++;
	}
};
int main() {
	CTest tst;
	cout << tst.operator++()<<endl;
	return 0;
}

 类外重载操作符

在类外重载,至少需要包含一个自定义类型,在类内的重载操作符函数有默认的this指针且为自定义类型,所以在定义函数时忽略了第一个参数,但类外重载没有隐藏的参数,一般比类内要多一个参数。但要注意是否与类内重载的函数有冲突

//类外重载
int operator+(CTest &tst,int a) {
	return tst.m_a + a;
}

类内、类外产生歧义,调用不明确:

class CTest {
public:
	int m_a;
	CTest() {
		m_a = 10;
	}
	//类内重载
	int operator+(int a) {
		return this->m_a+a;
	}
};
//类外重载
int operator+(CTest &tst,int a) {
	return tst.m_a + a;
}
int main() {
	CTest tst;
	//tst + 10; //error
	tst.operator+(10);//类内
	::operator+(tst, 10);//类外
	return 0;
}

 自定义重载输入、输出操作符,一般在类外重载:

class CTest {
public:
	int m_a;
};
//输入
istream& operator>>(istream& is,CTest& tst) {
	is >> tst.m_a;
	return is;
}
//输出
ostream& operator<<(ostream& os, CTest& tst) {
	os << tst.m_a;
	return os;
}

对于同一个操作符来说,写在不同的位置代表不同的含义,那么重载这个操作符需要注意参数的量、顺序不同代表不同的含义。

 //类内重载
    int operator*();//间接引用
    int operator*(int);//乘法

几个注意事项:

1.不能重载的运算符 :长度运算符sizeof、条件运算符: ?、成员选择符.、作用域运算符::等。

2.还有一些操作符只能在类内重载,赋值=下标[ ]调用(),和成员指向-> 操作符,它们必须被定义为类成员操作符。
3.重载操作符不能改变操作符的用法,原来有几个操作数、操作数在左边还是在右边,这些都不会改变。
4.运算符重载函数不能有默认的参数,否则就改变了运算符操作数的个数,这显然是错误的。
5.重载操作符不能改变运算符的优先级和结合性
6.不能创建新的运算符

对象类型转换

图中可以看到,我们反过来写会报错,类型不匹配。

此时可以重载某个类型,这样定义该类对象就可以像这个类型一样去使用。
引入转换函数(注:转换函数必须是非静态成员函数):

函数格式:


注:函数无参数、无返回值,但函数体中应该有return,且return的变量类型要和重载的类型一致。

下面两种都是错误的写法:

如果同时存在重载操作符和重载类型,那么优先匹配重载的操作符

当然也可以显示的调用类型转换函数


完整代码:

#include<iostream>
using namespace std;
class CTest {
public:
	int m_a = 1;
	int operator+(int a)
	{
		return m_a + a;
	}
	operator int()
	{
		int a = 0;
		return a;
	}
};
int main()
{
	CTest tst;
	int a = tst + 10; //operator+
	a = 10 + tst;     //operator int
	a = tst;          //operator int
}

实战训练:封装迭代器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值