所谓的操作重载实际上就是我们在自己创建类的时候,需要定义一些操作符的操作,比如说+ - < > = !=等等。在使用C++的标准库的时候,比如说string,我们习以为常的认为+就是连接,==就是比较,然而这些操作真正做什么是类中的操作符函数定义的,因此我们自己设计类的时候,也要对这些操作符进行重载,来达到我们的目的。
在c++中,所有的操作符都是由operator和其后要定义的运算符号组成。
输入输出运算符
对于输入输出运算符,它们必须是非成员函数。因为如果它们是成员函数,那么它们的左侧对象必然是类的一个对象。这样我们必须每次使用cout就要如下所示:1
2SalesData data;
data << cout;
而如果是非成员函数,我们就可以很自然的写成这种格式1
cout << data;
同时如果<<成员函数,那么它也必须是ostream的成员函数,如下所示,那么我们就需要修改标准库ostream,这是非法的。
一个输出运算符的重载例子
1 | ostream& operator<<(ostream& os, const SalesData& data) { |
第一个参数是ostream的引用,因为我们需要将内容写到os中,而返回值就是行参ostream
输入运算符的重载例子
1 | istream& operator>>(istream& is, SalesData& data) { |
算术运算符
算数运算符通常会计算两个对象并得到一个新的值,通常返回值是一个局部变量的副本。
operator+
operator+一般会使用复合赋值运算符operator+=来实现
1 | SalesData operator+(const SalesData& lhs, const SalesData& rhs) { |
关系运算符
关系运算符一般有< > <= >= == !=这几种
operator==
1 | bool operator==(const SalesData& lhs, const SalesData& rhs) { |
operator!=
operator!=一般由operator==实现1
2bool operator!=(const SalesData& lhs, const SalesData& rhs) {
return !(lhs == rhs);
赋值运算符
1 | SalesData& SalesData::operator=(const SalesData& rhs) { |
复合赋值运算符
复合赋值运算符做好定义为类的成员函数,这样我们可以充分的使用this指针来实现1
2
3
4SalesData& SalesData::operator+=(const SalesData& rhs) {
price += rhs.price;
return *this;
}
下标运算符
下标运算符一般定义为operator[],而且一般而言,会定义下标运算符的const以及非const版本1
2
3
4
5
6
7class StrVec {
public:
string& operator[](size_t n) {return elements[n];}
const string& operator[](size_t n) const {return elements[n];}
private:
string* elements;
}
递增递减运算符
递增递减运算符会比较特殊,因为它们有前置和后置两种方式
首先看前置的1
2
3
4
5
6
7
8
9
10
11
12
13class StrBlobPtr {
public:
StrBlobPtr& operator++() {
++curr;
return *this;
}
StrBlobPtr& operator--() {
--curr;
return *this;
}
private:
int curr;
}
而后置为了与前置区分,特别的增加了一个不被使用的int形参,并且利用了前置的函数
1 | class StrBlobPtr { |
因此在性能的场景下,也是推荐前置的方式。
成员访问运算符
成员访问运算符主要是指*和->
1 | class StrBlobPtr { |
函数调用运算符
1 | struct absInt { |