重载运算符
一,知识点总结
重载运算符函数可以对运算符做出新的解释,即定义用户所需要的各种操作。但运算符重载后,原有的基本语义不变,包括:
○不改变运算符的优先级
○不改变运算符的结合性
○不改变运算符所需要的操作数
○不能创建新的运算符
优先级和结合性主要体现在重载运算符的使用上,而操作数的个数不但体现在重载运算符的使用上,更关系到函数定义时的参数设定。
C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。
重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。
当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。
1, 重载运算符的语法形式
运算符函数是一种特殊的成员函数或者友元函数。成员函数的语句格式为:
类型 类名::operator op(参数表)
{
//相对于该类定义的操作
}
“类型”是函数的返回类型。“类名”是要重载该运算符的类。“op”表示要重载的运算符。函数名是“operator op”,由关键字operator和被重载的运算符op组成。“参数表”列出该运算符所需要的操作数。
用于类计算的运算符通常都要重载。但有两个运算符系统提供默认重载版本:
○赋值运算符“=”,系统默认重载为对象数据成员的复制:
○地址运算符“&”,系统默认重载为返回任何类对象的地址
2,用成员或友元函数重载运算符
(1) 一元运算符
一元运算符不论前置或后置,都要求有一个操作数:
Object op 或 op Object
当重载为成员函数时,编译器解释为:
Object.operator op()
函数operator op所需的操作数由对象Object通过this指针隐含传递,所以参数表为空
当重载为友元函数时,编译器解释为:
Operator op(Object)
函数operator op 所需的操作数由参数表的参数Object提供。
(2) 二元运算符
任何二元运算符都要求有左,右操作数:
ObjectL op ObjectR
当重载为成员函数时,编译器解释为:
ObjectL.operator op(OpjectR)
左操作数由对象ObjectL通过this指针传递,右操作数由参数ObjectR传递。
重载为友元函数时,编译器解释为:
operator op(ObjectL,ObjectR)
左右操作数都由参数传递。
不管是成员函数还是友元函数重载,运算符的使用方法都相同。但由于它们传递参数的方法不同,因此导致实现的代码不同,应用场合也不同。
2, 用成员函数重载运算符
成员运算符函数的原型在类的内部声明格式如下:
class X {
//…
返回类型 operator运算符(形参表);
//…
}
在类外定义成员运算符函数的格式如下:
返回类型 X::operator运算符(形参表)
{
函数体
}
对双目运算符而言,成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它是通过this指针隐含地传递给函数的。
一般而言,采用成员函数重载单目运算符时,以下两种方法是等价的:
@aa; // 隐式调用
aa.operator@(); // 显式调用
成员运算符函数operator @所需的一个操作数由对象aa通过this指针隐含地传递。因此,在它的参数表中没有参数。
3, 用友元函数重载运算符
Ø 在第一个参数需要隐式转换的情形下,使用友元函数重载
运算符是正确的选择
Ø 友元函数没有 this 指针,所需操作数都必须在参数表显式
声明,很容易实现类型的隐式转换
Ø C++中不能用友元函数重载的运算符有
= () [] ->
4, 几个典型运算符重载
设 A Aobject ;
运算符 ++和 - - 有两种方式:
前置方式:
++Aobject --Aobject
成员函数 重载
A :: A operator++ () ;
解释为:
Aobject . operator ++( ) ;
友元函数 重载
friend A operator++ (A &) ;
解释为:
operator ++( Aobject ) ;
后置方式:
Aobject ++ Aobject --
成员函数 重载
A :: A operator++ (int) ;
解释为:
Aobject . operator ++( 0 ) ;
友元函数 重载:
friend A operator++ (A &, int) ;
解释为:
operator++(Aobject, 0)
5, 重载赋值运算符
▲ 赋值运算符重载用于对象数据的复制
▲ operator= 必须重载为成员函数
▲重载函数原型为:
类名 & 类名 :: operator= ( 类名 ) ;
6, 重载流插入和流提取运算符
▲ istream 和 ostream 是C++预定义流类
▲ cin 是istream 的对象,cout是ostream的对象
Ø 运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
Ø 运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
Ø 用友元函数重载 << 和 >> ,输出和输入用户自定义的数据类型
重载输出运算符“<<”(只能被重载成友元函数,不能重载成成员函数)定义输出运算符“<<”重载函数的一般格式如下:
ostream& operator<<(ostream& out,class_name& obj)
{
out<<obj.item1;
out<<obj.item2;
.. .
out<<obj.itemn;
return out;
}
重载输入运算符“>>” (只能被重载成友元函数)
定义输入运算符函数“>>”重载函数的一般格式如下:
istream& operator>>(istream& in,class_name& obj)
{
in>>obj.item1;
in>>obj.item2;
. . .
in>>obj.itemn;
return in;
}
二,典型代码
重载“+”运算符
#include<bits/stdc++.h>
using namespace std;
class xiangjia
{
public:
xiangjia(){a=0;b=0;}
xiangjia(double e,double g){a=e;b=g;}
xiangjia operator+(xiangjia&c);
void display();
private:double a;double b;
};
xiangjia xiangjia::operator+(xiangjia&c)
{
return plus(a+c.a,b+c.b);
}
void xiangjia::display()
{
cout<<"("<<a<<","<<b<<","<<")";
}
int main()
{
xiangjia c(1,2),c1(2,3),c2;
c2=c+c1;
c2.display();
return 0;
}
赋值运算符重载
#include <iostream>
using namespace std;
class Distance
{
private:
int feet; // 0 到无穷
int inches; // 0 到 12
public:
// 所需的构造函数
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i){
feet = f;
inches = i;
}
void operator=(const Distance &D )
{
feet = D.feet;
inches = D.inches;
}
// 显示距离的方法
void displayDistance()
{
cout << "F: " << feet << " I:" << inches << endl;
}
};
int main()
{
Distance D1(11, 10), D2(5, 11);
cout << "First Distance : ";
D1.displayDistance();
cout << "Second Distance :";
D2.displayDistance();
// 使用赋值运算符
D1 = D2;
cout << "First Distance :";
D1.displayDistance();
return 0;
}
三,心得体会
对于重载运算符,感觉他很方便,我们可以自己定义运算,让那些符号按照我们的意愿去做某些运算,那些运算符本身功能是有限的 比如不能进行复数的加减 但是我们重载以后 就可以让它实数与实数相加,虚数与虚数相加,最后结果也是复数还有字符串string里也有很多重载的地方,像两个字符串也可以相加,等等 重载的主要目的是,简洁易懂,原理上其实也是通过函数实现的。所以重载运算符很方便,很省事。