一、什么是重载运算符
C++中,我们可以使用函数重载的方式,来重写多种形式的同一函数的不同实现,以自适应我们不同场景下的需求。而运算符重载与之类似,我们可以重写某些运算符,如+、-、*、/和%等,这样的方式,让我们的程序更加灵活,并更具有可读性。
二、重载运算符的使用
我们可以通过全局函数和类内的成员函数两种形式来实现重载运算符。
2.1 书写格式
以+举例子:
返回值类型 operator+(形参1, 形参2, ...) {
//函数实现
return XXX;
}
2.2 全局函数重载运算符
我们还是以加法来举例子。例子如下:
class Num {
public :
int value;
Num(int x) : value(x) {}
Num(): value(0) {}
//通过成员函数重载运算符+,参数为Num对象
Num operator+ (const Num& n0) {
return Num(this->value + n0.value);
}
};
Num类是一个拥有一个int成员的类。通过以上方式可以重载运算符+,在通过以下主函数调用:
int main() {
Num n1(6);
Num n2(4);
Num n3 = n1 + n2; //使用第一种重载的成员运算符+
cout << "n3.value = 6 + 4 = " << n3.value << endl;
return 0;
}
程序运行结果为:
2.3 成员函数重载运算符
和上边例子相同,以下是全局函数的实现方式(当然,形参需要两个加数):
//通过全局函数重载运算符+
Num operator+(const Num& n1, const Num& n2) {
return Num(n1.value + n2.value);
}
int main() {
Num n1(6);
Num n2(4);
Num n4 = n1 + n2; //使用全局函数重载的运算符+
cout << "n4.value = 6 + 4 = " << n4.value << endl;
return 0;
}
程序运行结果为:
三、重载运算符的规则
3.1 函数重载
重载运算符支持函数重载。还是以加法为例,例子如下:
class Num {
public :
int value;
Num(int x) : value(x) {}
Num(): value(0) {}
//通过成员函数重载运算符+,参数为Num对象
Num operator+ (const Num& n0) {
return Num(this->value + n0.value);
}
//重载运算符+的第二种重载形式,参数为int变量
Num operator+ (const int& n0) {
return Num(this->value + n0);
}
};
int main() {
Num n1(6);
Num n2(4);
Num n3 = n1 + n2; //使用第一种重载的成员运算符+
cout << "n3.value = 6 + 4 = "<< n3.value << endl;
n3 = n3 + 5; //使用第二种重载的成员运算符+
cout << "n3.value = 10 + 5 = "<< n3.value << endl;
return 0;
}
程序运行结果如下:
3.2 <<运算符的重载
<<运算符的重载可以实现链式编程,但只能通过全局函数。下边举一个例子:
#include <iostream>
using namespace std;
class Num {
public :
int v1;
Num(int x) : v1(x) {}
Num(): v1(0) {}
};
//通过全局函数重载运算符<<
ostream& operator<<(ostream &cout, Num &n) {
cout << "n : " << n.v1 << endl;
return cout;
}
int main() {
Num n(10);
cout << n << endl;
return 0;
}
3.3 前(后)置自增(减)运算符的重载
(以下为自增的例子,自减同理)
自增自减分为前置和后置两种,当以无参的成员函数重写时,是前置操作,
以带参的成员函数重写时,是后置操作(用占位参数int,编译器会自动判定为后置)。
#include <iostream>
using namespace std;
class MyInt {
private :
int value;
public :
MyInt(int v) : value(v) {}
MyInt() : value(0) {}
void setValue(int v) {
this->value = v;
}
int getValue() {
return value;
}
//前置自增
MyInt& operator++() { //必须返回引用,为了连续自加时不出错,始终对一个数据进行递增
value++;
return *this;
}
//后置自增
MyInt operator++(int) { //用占位参数int,表示后置操作
int v = value;
value++;
return MyInt(v);
}
//前置自减
MyInt& operator--() {
value--;
return *this;
}
//后置自减
MyInt operator--(int) {
MyInt m(value);
value--;
return m;
}
};
//重写<<运算符
ostream& operator<<(ostream &cout, MyInt num) {
cout << num.getValue();
return cout;
}
int main() {
MyInt n1(666);
cout << n1-- << endl;//666
cout << n1 << endl;//665
cout << --n1 << endl;//664
return 0;
}
3.4 =运算符的重载(深拷贝)
(注:作者使用的是DEV-C++软件,重复释放空间并未报错,但应该是不正确的)
为什么要重载类的=运算符呢?如果一个类中含有一个在堆空间动态申请的指针变量,在不重载=的情况下,编译器采用的形式是将每个变量的值进行对应赋值。请看下边的例子:
class Nmbr {
public :
int *value;
Nmbr(int v) {
value = new int(v);
}
~Nmbr(){
if(value != NULL) {
delete value;
value = NULL;
}
}
};
int main() {
Nmbr n1(666);
Nmbr n2(777);
cout << "Before" << endl;
cout << "n1 : " << n1.value << ":" << *(n1.value) << endl;
cout << "n2 : " << n2.value << ":" << *(n2.value) << endl;
n2 = n1;
cout << "After" << endl;
cout << "n1 : " << n1.value << ":" << *(n1.value) << endl;
cout << "n2 : " << n2.value << ":" << *(n2.value) << endl;
return 0;
}
程序运行的结果为:
结果中我们看到,通过赋值后,变量n1的value和变量n2的value的值是相同的,也就是说他们指向同一个空间。但在程序运行结束后,会分别执行n1与n2的析构方法,也就是会对同一空间进行delete,这是不正确的。
正确的拷贝,也就是深拷贝,应该是为n2也动态申请一段空间,这个空间中的值与n1的相同,但不应该是同一个空间。正确的拷贝代码如下:
class Nmbr {
public :
int *value;
Nmbr(int v) {
value = new int(v);
}
~Nmbr(){
if(value != NULL) {
delete value;
value = NULL;
}
}
Nmbr& operator=(Nmbr n) {
printf("Here!!!\n");
//现将原变量释放干净
if(value != NULL) {
delete value;
value = NULL;
}
int v = *(n.value);
value = new int(v);
return *this;
}
};
int main() {
Nmbr n1(666);
Nmbr n2(777);
cout << "Before" << endl;
cout << "n1 : " << n1.value << ":" << *(n1.value) << endl;
cout << "n2 : " << n2.value << ":" << *(n2.value) << endl;
n2 = n1;
cout << "After" << endl;
cout << "n1 : " << n1.value << ":" << *(n1.value) << endl;
cout << "n2 : " << n2.value << ":" << *(n2.value) << endl;
return 0;
}
在上述运行结果中,我们可以看到,复制后的n1与n2的value值是不同的,代表这是两段空间。