一、操作符重载概念
(1)什么是重载
函数可以拥有相同的函数名, 参数列表(参数个数,参数类型)不同
通俗的讲:重载就是一个词有多种不同的含义。准确地说:在C++程序中,同一作用域内函数可以拥有相同的函数名,参数列表(参数个数,参数类型)不同
(2) 为什么要操作符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
运算符重载是为了解决类对象之间的运算的,通常的运算符只用于算术运算,如常量int之间,因为编译器已经定义了;而一个类两个对象之间成员进行运算必须重新定义,让编译器在遇到对象运算时能按我们要求的进行运算,这就是运算符重载的意义,即重定义运算符,因此你可以看到,运算符重载就是为类对象服务的,那么两个对象的成员进行运算那必须先获得对象本身啦,所以运算符重载参数必须含有类指针或引用,这是主要客户。
(3)重载的几种方式
(1)成员函数重载方式
(2)友元函数重载方式
(3)普通函数
大多数运算符既可以友元重载也可以成员重载,但是C++要求’=’、’[]’、’()’、’->'操作符必须被定义为类的成员操作符,把这些操作符通过全局函数进行重载时会出现编译错误
(4)操作符重载的限制:
重载后操作符的操作数至少有一个是用户定义类型;
不能违反原来操作数的语法规则;
不能创建新的操作符;
重载运算符的函数不能有默认的参数;
不能重载的操作符包括(以空格分隔):sizeof . .* :: ?: RTTI类型运算符
=、()、[]、以及 ->操作符只能被类的成员函数重载
二、operator关键字
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
注意:
不能通过连接其他符号来创建新的操作符:比如operator@ 重载操作符必须有一个类类型或者枚举类型的操作数 用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义 ,内置类型语言已经定义了其逻辑功能,不能对其做改变。运算符重载相当于在自定义类型中定义另一种逻辑。 作为类成员的重载函数时,其形参看起来比操作数数目少1个成员函数的操作符有一个默认的形参this,限定为第一个形参 注意以下的运算符不能重载
作用域操作符:::
条件操作符:?
点操作符:.
指向成员操作的指针操作符:->* .*
预处理符号:# , sizeof
. 和 .* 运算符不能重载是为了保证访问成员的功能不能被改变,域运算符和sizeof运算符的运算对象是类型而不是变量或一般表达式,不具备重载的特征。
三、操作符重载
(1)自增自减运算符重载
#include <iostream>
using namepace std;
class Complex
{
int real;
int img;
public:
Complex():real(0),img(0){};
Complex(int r,int i):real(r),img(i){};
Complex addNunber(Complex &p1)
{
Complex p3;
p3.real = real + p1.real;
p3.img = img + p1.img;
}
void display() const
{
cout << real << endl;
cout << img << endl;
}
// 前置++版本 返回值为引用 其表示进行++之后的对象
Complex &operator++()
{
real++;
img++;
return *this;
}
// 后置++ 其表示++之前的值的对象 参数int 仅仅是为了区别重载
Complex operator++(int i)
{
Complex temp = *this;
real++;
img++;
return temp;
}
};
int main(int argc, char const *argv[])
{
Complex c3;
++c3;
c3++;
c3.display();
return 0;
}
(2)赋值运算符重载
#include <iostream>
using namespace std;
class Complex
{
int real;
int img;
public:
Complex():real(0),img(0){};
Complex(int r,int i):real(r),img(i){};
void display() const
{
cout << real << endl;
cout << img << endl;
}
// 赋值运算符重载函数必须定义为成员函数
Complex &operator = (const Complex &c)
{
cout << c.img << endl;
if (this != &c)
{
real = c.real;
img = c.img;
}
return *this;
}
};
int main(int argc, char const *argv[])
{
Complex c1;
Complex c2 = Complex(1,2);
Complex c3;
c3 = c2 = c1 = c2;
c3.display();
return 0;
}
(3)输入输出操作符重载
#include <iostream>
using namespace std;
class Complex
{
int real;
int img;
public:
Complex():real(0),img(0){};
Complex(int r,int i):real(r),img(i){};
Complex addNumber(Complex &p1)
{
Complex p3;
p3.real = real + p1.real;
p3.img = img + p1.img;
return p3;
}
void display() const
{
cout << real << endl;
cout << img << endl;
}
// 输出操作符重载 不能定义为成员函数
friend ostream & operator<<(ostream &out, const Complex &c);
friend istream & operator>>(istream &in,Complex &c);
};
//因为不需要修改值,所以要将c定义为const类型
ostream & operator<<(ostream &out, const Complex &c)
{
out << c.real << '+' << c.img;
return out;
}
// 因为需要修改值,所以不要将c定义为const类型
istream & operator>>(istream &in,Complex &c)
{
in >> c.real;
in >> c.img;
return in;
}
int main(int argc, char const *argv[])
{
Complex c1;
Complex c2 = Complex(1,2);
Complex c3;
// 不能进行连续输出
cout << "该值为" << c3 << c2 << c1;
cin >> c3;
cout << c3;
c3.display();
return 0;
}
注意:
1、输入输出运算符重载函数只能定义为友元函数 因为完全不需要this指针
2、 为了能够进行连续输出 需将返回值定义为 ostream的引用
3、 尽量不要在这个函数当中添加 换行符