在C++中,函数重载有两种方式:
- 直接在类内部声明,只需要一个参数
bool operator ==(const Node &node) {
return this->x == node.x and this->y == node.y;
}
- 在类外部声明,需要两个参数
bool operator<(const Node &a, const Node &b) {
if (a.x != b.x)return a.x < b.x;
else return a.y < b.y;
}
除了手动重载这些函数,还可以使用模板函数进行快速重载,就像C#中的扩展方法和Go里面的struct一样给class插上“翅膀”。方法是:使用utility中的rel_ops命名空间。
这个命名空间实现了以下模板函数:
namespace rel_ops {
template <class T> bool operator!= (const T& x, const T& y);
template <class T> bool operator> (const T& x, const T& y);
template <class T> bool operator<= (const T& x, const T& y);
template <class T> bool operator>= (const T& x, const T& y);
}
如上所示,rel_ops命名空间实现了四种运算符,我们只需要自己实现==
和<
两个运算符就能够实现以上四种运算符了。
请看一个完整的例子。
#include<iostream>
#include<iso646.h>
using namespace std;
class Node {
public:
int x, y;
Node(int x, int y) {
this->x = x, this->y = y;
}
bool operator ==(const Node &node) {
return this->x == node.x and this->y == node.y;
}
};
bool operator<(const Node &a, const Node &b) {
if (a.x != b.x)return a.x < b.x;
else return a.y < b.y;
}
int main() {
using namespace std::rel_ops;
Node m(3, 4), n(2, 5);
cout << (m > n) << endl;
cout << (m <= n) << endl;
return 0;
}
还有一个关键之处:左移运算符和移位运算符都是<<
,但是因为它们接受的参数不一样,所以可以同时重载。
#include <iostream>
using namespace::std;
class MyClass
{
public:
MyClass(int a, int b)
{
this->a = a;
this->b = b;
}
void print_Myclass() {
cout << this->a << '+' << b << 'i' << endl;
}
//输出运算符和左移运算符虽然样子一样,但是参数不一样,所以相当于运算符重载
friend ostream & operator<<(ostream &os, MyClass &c);
MyClass operator<<(int cnt) {
return MyClass(a << cnt, b << cnt);
}
private:
int a;
int b;
};
//使用友元访问私有变量
ostream & operator<<(ostream &os, MyClass &c) {
os << c.a << '+' << c.b << 'i';
return os;
}
void main() {
MyClass c(3, 4);
cout << c << endl;
MyClass cc = c << 1;
cout << cc << endl;
//下面这句话会报错,因为cc<<1返回来的对象是一个临时对象,而cout<<需要的参数却是MyClass&类型的对象
//cout << (cc << 1) << endl;
}
虽然移位运算符正常情况下接受的参数是int,表示移位的个数,但实际上这个参数可以是任何类型,移位运算符完全由用户掌控,但是有两点需要注意:
- 运算符的参数个数必须一致
- 重载运算符后的优先级和结合性都不会改变。
MyClass operator<<(double cnt) {
return MyClass(a * cnt, b *cnt);
}
C++中可以重载的运算符包括
+ - * / % ^ & | ~
! = < > += -= *= /= %
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- ->* ‘ ->
[] () new delete new[] delete[]
不能重载的操作符是类属关系运算符 如:
. :: .* ?: sizeof