前言:C++的运算符重载与友元函数是像类似Java这种纯的面向对象编程语言所不具备的特征,那么使用运算符重载与友元函数到底能带来什么样的不同呢?
举个例子,假如需要实现一个复数的加减法,用Java实现后两个复数相加的代码可能如下:
public static void main(String[] args) {
ComplexNumber a = new ComplexNumber(10.0, 8.0);
ComplexNumber b = new ComplexNumber(6.0, 5.0);
ComplexNumber c = a.add(b);
ComplexNumber d = a.sub(b);
}
注意到两个复数类相加只能调用复数类中的方法,并不能直接使用 a + b这种形式,但是C++中却提供了运算符重载来解决这个问题,同样实现复数的加减法其代码如下:
#include <iostream>
#include <string>
using namespace std;
using std::string;
class ComplexNumber
{
public:
double real; // 实数
double imaginary; // 虚数
public:
ComplexNumber(double real = 0.0, double imaginary = 0.0);
ComplexNumber operator+(const ComplexNumber &b);
ComplexNumber operator-(const ComplexNumber &b);
friend ostream & operator<<(ostream &os, const ComplexNumber &cn);
};
ComplexNumber::ComplexNumber(double real, double imaginary)
{
this->real = real;
this->imaginary = imaginary;
}
ComplexNumber ComplexNumber::operator+(const ComplexNumber &b)
{
ComplexNumber cn;
cn.real = this->real + b.real;
cn.imaginary = this->imaginary + b.imaginary;
return cn;
}
ComplexNumber ComplexNumber::operator-(const ComplexNumber &b)
{
ComplexNumber cn;
cn.real = this->real - b.real;
cn.imaginary = this->imaginary - b.imaginary;
return cn;
}
ostream & operator<<(ostream &os, const ComplexNumber &cn)
{
os << "(" << cn.real << " + " << cn.imaginary << "i)";
return os;
}
int main()
{
ComplexNumber a(10.0, 8.0);
ComplexNumber b(6.0, 5.0);
ComplexNumber c = a + b;
ComplexNumber d = a - b;
cout << a << " + " << b << " = " << c << endl;
cout << a << " - " << b << " = " << d << endl;
return 0;
}
其运行结果如下:
(10 + 8i) + (6 + 5i) = (16 + 13i)
(10 + 8i) - (6 + 5i) = (4 + 3i)
哈哈哈,这样调用的感觉是不是棒呆了,完全符合加减法的书写习惯。而在C++中只要使用operator关键字,便可实现运算符的重载,运算符重载遵循如下规则:
- C++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已有的运算符;
- 重载之后运算符的优先级和结合性都不会改变;
- 运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。一般来说,重载的功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。
注:操作符可以重载的运算符包括:
- 算术运算符:+,-,*,/,%,++,–;
- 位操作运算符:&,|,~,^,<<,>>
- 逻辑运算符:!,&&,||;
- 比较运算符:<,>,>=,<=,==,!=;
- 赋值运算符:=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=;
- 输入输出运算符:<<, >>
- 其他运算符:[],(),->,,(逗号运算符),new,delete,new[],delete[],->*。
不可重载的运算符包括:
- 成员运算符:.
- 指针运算符:*
- 作用域运算符:::
- sizeof
- 条件运算符:?:
其中,在上面的例子中,重载输入输出运算符时必须使用友元函数,而友元函数则是指某些虽然不是类成员却能够访问类的所有成员的函数,即如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中的该函数必须要是类B的友元函数。友元函数的定义使用friend 关键字,其实现方式大致如上所示。
以此,仅为对C++运算符重载与友元函数的一个简单使用总结,实际运用中应该灵活运用,以实现其最大作用。
路漫漫兮其修远兮,任重而道远。