第七章总结:运算符重载
知识点总结:
不能重载的算符
. :: .* ?: sizeof
可以重载的运算符
+ - * / % ^ & | ~
! = < > += -= *= /= %
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- ->* ‘ ->
[] () new delete new[] delete[]
重载运算符的限制
重载运算符函数可以对运算符作出新的解释,但原有基本语义不变:
不改变运算符的优先级
不改变运算符的结合性
不改变运算符所需要的操作数
不能创建新的运算符
运算符函数可以重载为成员函数或友元函数
用成员或友元函数重载运算符
一元运算符
Object op 或 op Object
重载为成员函数,解释为:
Object . operator op ()
操作数由对象Object通过this指针隐含传递
重载为友元函数,解释为:
operator op (Object)
操作数由参数表的参数Object提供
二元运算符
Object L op ObjectR
重载为成员函数,解释为:
ObjectL . operator op ( ObjectR )
左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递
重载为友元函数,解释为:
operator op ( ObjectL, ObjectR )
左右操作数都由参数传递
(一)、用成员函数重载运算符
成员运算符函数的原型在类的内部声明格式如下:
class X {
//…
返回类型 operator运算符(形参表);
//…
}
在类外定义成员运算符函数的格式如下:
返回类型 X::operator运算符(形参表)
{
函数体
}
双目运算符重载为成员函数
对双目运算符而言,成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它是通过this指针隐含地传递给函数的。
一般而言,如果在类X中采用成员函数重载双目运算符@,成员运算符函数operator@ 所需的一个操作数由对象aa通过this指针隐含地传递,它的另一个操作数bb在参数表中显示,aa和bb是类X的两个对象,则以下两种函数调用方法是等价的:
aa @ bb; // 隐式调用
aa.operator @(bb); // 显式调用
单目运算符重载为成员函数
对单目运算符而言,成员运算符函数的参数表中没有参数,此时当前对象作为运算符的一个操作数。
一般而言,采用成员函数重载单目运算符时,以下两种方法是等价的:
@aa; // 隐式调用
aa.operator@(); // 显式调用
成员运算符函数operator @所需的一个操作数由对象aa通过this指针隐含地传递。因此,在它的参数表中没有参数。
(二)、用友元函数重载
1.在第一个参数需要隐式转换的情形下,使用友元函数重载
运算符是正确的选择
2.友元函数没有 this 指针,所需操作数都必须在参数表显式
声明,很容易实现类型的隐式转换
3.C++中不能用友元函数重载的运算符有
= () [] ->
成员运算符函数与友元运算符函数的比较
(1) 成员运算符函数比友元运算符函数少带一个参数(后置的++、--需要增加一个形参)。
(2) 双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当操作数类型不相同时,必须使用友元函数。
三、重载赋值运算符
赋值运算符重载用于对象数据的复制
operator=必须重载为成员函数
重载函数原型为:
类名 & 类名 :: operator= ( 类名 ) ;
(一)、重载运算符[]和()
运算符 [] 和 () 是二元运算符
[] 和 () 只能用成员函数重载,不能用友元函数重载
重载下标运算符 []
[] 运算符用于访问数据对象的元素
重载格式 类型 类 :: operator[] ( 类型 ) ;
重载函数调用符 ()
() 运算符用于函数调用
重载格式 类型 类 :: operator() ( 参数表 ) ;
(二)、重载流插入和流提取运算符
运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
用友元函数重载 << 和 >> ,输出和输入用户自定义的数据类型
重载输出运算符“<<”(只能被重载成友元函数,不能重载成成员函数)
重载输入运算符“>>”(只能被重载成友元函数)
例题:
例7-10 设计一个集合类,用无符号整数数组表示集合,重载运算符实现集合的基本运算,以及集合元素的输入、输出。
//setTypeHead.h
#include<iostream>
using namespace std;
//集合类
class setType
{ public:
setType(unsigned e=128 ); //构造函数
setType(const setType & B ); //复制构造函数
~setType(); //析构函数
setTypeoperator+= ( unsigned x ); //重载+=,把元素x并入集合
setTypeoperator= ( setType B ); //重载=,集合变量赋值
setTypeoperator() (unsigned x=0); //重载(),集合置元素x,默认置空
setTypeoperator+ ( setType B ); //重载+,求并集
setType operator* ( setType B ); //重载*,求交集
setTypeoperator- ( setType B ); //重载-,求差集
booloperator<= ( setType B ); //重载<=,判集合蕴含
//重载!运算符,判空集。集合空返回false,否则返回true
booloperator ! ();
//重载<,判元素属于集合
friend bool operator< ( unsigned x, setTypeA );
//重载>>,输入集合元素
friendistream & operator>> ( istream &input, setType &A );
//重载<<,输出集合的全部元素
friendostream & operator<< ( ostream &output, setType &A );
private:
unsigned *set; //建立动态数组指针
unsigned n; //数组长度
unsigned e; //全集元素个数
};
//test.cpp
#include"setTypeHead.h"
int main()
{ setType setA, setB, setC; unsigned x;
cout << "Input the elements ofsetA, 1-128, until input 0 :\n";
cin >> setA; //输入setA的元素
cout << "Input the elements ofsetB, 1-128, until input 0 :\n";
cin >> setB; //输入setB的元素
cout << "setA = " <<setA << endl; //输出setA的元素
cout << "setB ="<<setB << endl; //输出setB的元素
cout << "Input x: "; cin>> x;
setA += x; //把元素x并入setA
cout << "Put " << x<< " in setA = " << setA << endl;
setC = setA + setB; //求并集
cout << "setC = setA+setB = " << setC<< endl;
setC = setA * setB; //求交集
cout << "setC = setA*setB = " << setC<< endl;
setC = setA - setB; //求差集
cout << “setC = setA-setB = ” << setC << endl;
//判断setA是否蕴含于setB
if( setA <= setB ) cout << "setA <= setB\n";
else cout << "not setA <=setB\n";
cout << "Input x: "; cin >> x;
//判断元素x是否属于setA
if( x < setA ) cout<< x << " in " << setA << "\n";
else cout << x << " not in "<< setA << "\n";
setC = setA + setB + setC; //多个集合变量运算
cout << "setC = setA+setB+setC = " << setC<< endl;
setC(); //置setC为空集
cout<<"setC = " << setC << endl;
}
个人心得:
重载运算符教会了我许多,在之后的写程序中有非常大的用处,很开心学会了一点知识,最近的努力没有白费。