C++允许用户定义多个名称相同但是特征标(参数列表)不同的函数,这被称作是函数重载或者函数多态(有别于C++多态性的概念)。运算符重载将重载的概念扩充到运算符,目前C/C++编译器以实现许多操作符重载,如*运算符用于地址值上将得到存储在该地址值上的值。
总之,运算符重载就是对现有的运算符功能根据用户的需要进行扩充,满足开发过程中的需求。同时需要遵守编译器的规定。。本文对学习过程中的运算符重载的成员函数方法和友元函数方法进行一次总结。
可以重载的运算符包括:
+ - * / % ^ & | ~
! = < > += -= *= /= %=
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- ->* ' ->
[] () new delete new[] delete[]
不能重载的运算符包括
. :: .* ?: sizeof
重载运算符函数可以对运算符做出新的解释,但原有的基本寓意保持不变
①不改变运算符的优先级
②不改变运算符的结合性
③不改变运算符所需要的操作数
④不能创建新的运算符
函数写法:
运算符重载的写法和函数的写法类似,其本质就是一个函数,但是其必须按照一定的套路进行才行。
①友元函数写法
返回类型 operator 运算符(参数列表)
{
业务内容
}
在类的内部将该函数声明为友元函数。
对于二元运算符,其左右操作数都由参数列表传递。
调用分析:
//函数声明Object operator+(Object& obj1,Object& obj2)
Object obj1,obj2;
Object obj3 = obj1+obj2;
//等效于obj3 = operator+(obj1,obj2)
②成员函数写法
返回类型 类名:: operator 运算符(参数列表)
{
业务内容
}
对二元运算符,其参数的传递遵循:左操作数由this指针专递,右操作数由参数列表传递。调用分析:
//函数声明Object Object::operator+(Object& obj)
Object obj1,obj2;
Object obj3 = obj1+obj2;
//等效于obj3 = obj1.operator+(obj2)
友元函数重载运算符注意事项:
①友元函数重载运算符常用于运算符的左操作数和右操作数不同的情况下;
②当左操作数不是类对象时,即不能调用成员函数的时候,必须使用友元函数重载。如c2=2+c1;(c1、c2是C类的对象);
③友元函数没有this指针
④不能用友元函数重载的操作符有()、[]、=、->四个符号。
何时选用友元函数方法?何时选用成员函数方法?
- 当左操作数不是可操作的类对象的时候,选择使用友元函数方法,如左操作数是常数、输入输出流等对源码无法操作的情况;
- 友元函数常用于左右操作数类型不同的情况;
- ()、[]、=、->这四个符号必须用成员函数方法。
链式编程支持
例如实现下述例子中c1、c2、c3三个对象的相加,重载<<运算符后可以连续输出等。
//函数1
//友元函数重载流操作符,返回ostream对象的引用
ostream& operator<<(ostream& out, Complex& c)
{
out << c.real << " + " << c.imag << endl;
out << "今天天气真好!" << endl;
return out;
}
//函数2
//友元函数重载流操作符,返回值为void
void operator<<(ostream& out, Complex& c)
{
out << c.real << " + " << c.imag << endl;
out << "今天天气真好!" << endl;
}
以上重载函数的返回值为void时也是正确的,只是不支持链式编程了。即下述代码用函数1运行成功输出,而用函数2运行就报错。原因如下:
cout<<c1<<"美好的一天从敲代码开始!"<<endl;
这条代码等效于:operator<<(cout,c1).operator<<("美好的一天从敲代码开始!");
其调用的两个<<重载函数并非同一个函数!!!!!!
【一个例子】
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
class Complex
{
private:
int real;
int imag;
friend Complex operator-(const Complex& c1, const Complex& c2);
//friend Complex& operator++(Complex& c);
// friend Complex operator++(Complex& c, int);
//友元函数重载前置--运算符
friend Complex& operator--(Complex& c);
//友元函数重载后置--运算符
friend Complex operator--(Complex& c, int);
friend ostream& operator<<(ostream& out, Complex& c);
friend istream& operator>>(istream& in, Complex& c);
public:
Complex()
{
}
Complex(int _real,int _imag)
{
real = _real;
imag = _imag;
}
~Complex()
{
}
void Print()
{
cout << real << " + " << imag << "i" << endl;
}
Complex operator+(const Complex& c)
{
Complex tmp;
tmp.real = this->real + c.real;
tmp.imag = this->imag + c.imag;
return tmp;
}
//成员函数重载前置++
Complex& operator++()
{
this->real++;
this->imag++;
return *this;
}
//成员函数重载后置++
Complex operator++(int)
{
Complex tmp(this->real, this->imag);
this->real++;
this->imag++;
return tmp;
}
};
Complex operator-(const Complex& c1, const Complex& c2)
{
Complex tmp;
tmp.real = c1.real - c2.real;
tmp.imag = c1.imag - c2.imag;
return tmp;
}
友元函数重载前置++运算符
//Complex& operator++(Complex& c)
//{
// c.real++;
// c.imag++;
// return c;
//}
友元函数重载后置++运算符
//Complex operator++(Complex& c, int)
//{
// Complex tmp(c.real, c.imag);
// c.real++;
// c.imag++;
// return tmp;
//}
//友元函数重载前置--运算符
Complex& operator--(Complex& c)
{
c.real--;
c.imag--;
return c;
}
//友元函数重载后置++运算符
Complex operator--(Complex& c, int)
{
Complex tmp(c.real, c.imag);
c.real--;
c.imag--;
return tmp;
}
//友元函数重载流操作符
ostream& operator<<(ostream& out, Complex& c)
{
out << c.real << " + " << c.imag << endl;
out << "今天天气真好!" << endl;
return out;
}
istream& operator>>(istream& in, Complex& c)
{
in >> c.real >> c.imag;
return in;
}
int main()
{
Complex c1(1, 2), c2(3, 4);
//Complex c3 = c1 + c2;
//c3.Print();
// c1++;
/*Complex c5 = c1-- + c2--;
c5.Print();
c1.Print();
c2.Print();
Complex c6 = --c1 + --c2;
c6.Print();
c1.Print();
c2.Print();*/
//Complex c4 = c3 - c2;
//c4.Print();
//++c1;
//c1.Print();
cout << c1<<"世界很美好!";
cin >> c1;
c1.Print();
system("pause");
return 0;
}