运算符重载学习总结

运算符重载

一、知识点总结

1、重载运算符的限制

(1)不能重载的运算符:. :: .* ?: sizeof

(2)可以重载的运算符:+ - * /  % ^ & | ~ ! = < > += -= *= /= % ^= &= |= << >> >>= <<= == != <= >= && || ++ --  ->* ' -> [] () new delete new[] delete[]

(3)重载运算符函数可以对运算符做出新的解释,但原有基本语义不变:

不改变运算符的优先级

不改变运算符的结合性

不改变运算符所需要的操作数

不能创建新的运算符

2、运算符函数可以重载为成员函数或友元函数

(1)一元运算符

Object op 或 op Object

重载为成员函数解释为:Object . operator op ()

操作数由对象Object通过this指针隐含传递

重载为友元函数解释为:operator op (Object)

操作数由参数表的参数Object提供

(2)二元运算符

ObjectL op ObjectR

重载为成员函数解释为:ObjectL.operator op (ObjectR)

左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递

重载为友元函数解释为:operator op (ObjectL,ObjectR)

左右操作数都由参数传递

(3)用成员函数重载运算符

成员运算符函数的原型在类的内部声明格式如下:

class X{

//...

返回类型operator 运算符(形参表);

//...

}

在类外定义成员运算符函数的 格式如下:

返回类型X::operator运算符(形参表)

{

函数体

}

(4)双目运算符重载为成员函数

对双目运算符而言,成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它是通过this指针隐含地传递给函数的。

(5)一般而言,如果在类X中采用成员函数重载双目运算符@,成员运算符函数operator@所需的一个操作数由对象aa通过this指针隐含地传递,他的另一个操作数bb在参数表中显示,aa和bb是类X的两个对象,则以下两种函数的调用方法等价:

aa@bb;//隐式调用

aa.operator @ (bb);//显示调用

(6)单目运算符重载为成员函数

对单目运算符而言,成员运算符函数的参数表中没有参数,此时当前对象作为运算符的一个操作数。

一般而言,采用成员函数重载单目运算符时,以下两种方法等价:

@aa;//隐式调用

aa.operator@();//显示调用

成员运算符函数operator@所需的一个操作数由对象aa通过this 指针隐含地传递,因此,在他的参数表中没有参数。

(7)用友元函数重载

友元函数重载运算符常用于运算符左右操作数类型不同的情况。

在第一个参数需要隐式转换的情形下,使用友元函数重载运算符是正确的选择。

友元函数没有this指针,所需的操作数都必须在参数表显示声明,很容易实现类型的隐式转换。

C++中不能用友元函数重载的运算符有= () [] ->

成员运算符函数与友元运算符函数的比较
(1)成员运算符函数比友元运算符函数少带一个参数(后置的++ --需要增加一个形参)。
(2)双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当操作数类型不相同时,必须使用友元函数。
3
(1)运算符++和--有两种方式:
前置方式:++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);


(2)重载赋值运算符
赋值运算符重载用于对象数据的复制
operator=必须重载为成员函数
重载函数原型为:类名&类名::operator=(类名);
//修改对象时调用重载复制运算符函数
(3)重载运算符[]和()
运算符[]和()是二元运算符
[]和()只能用成员函数重载,不能用友元函数重载
1)重载下标运算符[]
[]运算符用于访问数据对象的元素
重载格式   类型 类::operator[](类型);

设x是类X的一个对象,则表达式x[y]可被解释为x.operator[](y)
2)重载函数调用符()
()运算符用于函数调用
重载格式 类型 类::operator()(参数表);

设x是类X的一个对象,则表达式x(arg1,arg2,…)可被解释为x.operator()(arg1,arg2,...)
(3)重载流插入和流提取运算符
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;
}

二、感悟

1、重载运算符:作用是扩展应用范围,一般在类内进行。

2、成员函数重载:当前对象是第一个操作数,第一个操作数一定是对象本身,双目再加一个操作数。

3、友员函数重载比成员函数重载多一个参数。

4、友员:

(1)参数个数与操作数一致。

(2)不加类名限定。

5、自加自减:

成员函数:自加前置不需参数,本身对象是操作数;后置方式必须写参数(无用),第二个操作数是伪操作数。 

6、a=n++;//把n赋值给a,n再加1

7、记录类:不能用浅复制,不是自己定义的是浅复制。

8、重载运算符主要应用于数据类,操作类基本不用。

9、不同之处:

(1)c1+c2:用c1的重载运算符函数,c2作为参数。

(2)c2+c1:用c2的重载运算符函数,c1作为参数。

10、对象调用成员函数完成重载。

11、友元函数重载:第一个操作数不再是对象本身。

12、返回的一定是自定义的对象。

13、(1)前加:值本身加一再返回;

       (2)后加:值先参加其他运算再加一。

14、C++不允许将对象的值整体赋值给另一个对象,第一个操作数一定是对象本身。

15、protected:继承/保护的访问权限,比私有大比公有小。

16、重载赋值运算符:用一个已知对象的内容赋值给另一个对象,几个对象都已经存在时修改对象调用重载赋值运算符。

17、复制构造函数在创建对象时起作用,之后就不再起作用。

18、重载[]:确定在数组中的位置,必须使用成员函数重载,不能使用友元函数重载。

19、重载():用类的方式写了一个函数,是函数的另一种定义形式。

20、第一个操作数一定是流对象。

21、>>:提取运算符

       <<:插入运算符

22、重载输入输出运算符:将数据对象整体输入输出。

23、

(1)复制构造函数:用一个已知对象创建另一个对象

(2)重载赋值运算符:用一个已知对象改变另一个对象

24、静态数据:属于所有对象共同拥有

25、只有静态函数可以操作静态数据

26、在一个类中重载<和>的内容不能相同,否则矛盾

27、用友元函数重载输入输出流,因为第一个成员不是成员对象

28、string 中的 find 是发现一个子串

29、当用两种或两种以上方式比较时,可以建立比较函数。

三、经典样例

 #include <iostream.h> 
enum style_enum{zero, one, two, three }; class CFraction {
private:  int nume; // 分子 
int deno; // 分母 
public: 
 CFraction(int nu=0,int de=1):nume(nu),deno(de){} //构造函数,初始化用 
void simplify(); //化简(使分子分母没有公因子)
  //输入输出重载 
friend ostream& operator<<(ostream &out,const CFraction &cf);
 friend istream& operator>>(istream &in,CFraction &cf);
 //加减乘除,结果需要化简 
friend CFraction operator+(const CFraction &lcf,const CFraction &rcf); 
friend CFraction operator-(const CFraction &lcf,const CFraction &rcf); 
friend CFraction operator*(const CFraction &lcf,const CFraction &rcf);  friend CFraction operator/(const CFraction &lcf,const CFraction &rcf);  //关系运算符  friend bool operator>(const CFraction &lcf,const CFraction &rcf); 
friend bool operator<(const CFraction &lcf,const CFraction &rcf); 
friend bool operator>=(const CFraction &lcf,const CFraction &rcf); 
friend bool operator<=(const CFraction &lcf,const CFraction &rcf); 
friend bool operator==(const CFraction &lcf,const CFraction &rcf); 
friend bool operator!=(const CFraction &lcf,const CFraction &rcf); 
 //取+、-一目运算符 
CFraction operator+(); 
CFraction operator-(); }; 
void CFraction::simplify() 
{  int v1 = nume; 
int v2 = deno; 
while(v2)  { 
int temp = v2; 
v2 = v1 % v2; 
v1 = temp;  }
  nume /= v1;
  deno /= v1;
  if(deno < 0) 
{  deno = -deno;  nume = -nume;  } } 
//输出重载
 ostream& operator<<(ostream &out,const CFraction &cf)
 {  out << cf.nume << '/' << cf.deno;  return out; } 
//输入重载
 istream& operator>>(istream &in,CFraction &cf) {  char ch; 
while(1)
  {  in >> cf.nume >> ch >> cf.deno;  if(cf.deno == 0) 
cerr << "分母为0请重新输入\n";  else if(ch != '/') 
cerr << "格式错误(形如m/n)请重新输入\n"; 
else break;  } 
return in; } 
//加法重载 
CFraction operator+(const CFraction &lcf,const CFraction &rcf)
 {  CFraction cf;
  cf.nume = lcf.nume*rcf.deno + lcf.deno*rcf.nume; 
cf.deno = lcf.deno*rcf.deno; 
cf.simplify();
  return cf; } 
//减法重载
 CFraction operator-(const CFraction &lcf,const CFraction &rcf)
 {  CFraction cf;
  cf.nume = lcf.nume*rcf.deno - rcf.nume*lcf.deno; 
cf.deno = lcf.deno*rcf.deno; 
cf.simplify(); 
return cf; } 
//乘法重载
 CFraction operator*(const CFraction &lcf,const CFraction &rcf)
 {  CFraction cf;
  cf.nume = lcf.nume*rcf.nume;
  cf.deno = lcf.deno*rcf.deno; 
cf.simplify();
  return cf; }
 //除法重载
 CFraction operator/(const CFraction &lcf,const CFraction &rcf)
 {  CFraction cf;  cf.nume = lcf.nume*rcf.deno; 
cf.deno = lcf.deno*rcf.nume;
  cf.simplify(); 
return cf; } 
//取正重载
 CFraction CFraction::operator+() 
{  simplify(); 
if(nume < 0) 
nume = -nume;
  return *this; }
 //取负重载
 CFraction CFraction::operator-()
 {  simplify(); 
nume = -nume;
  return *this; } 
//大于号重载 
bool operator>(const CFraction &lcf,const CFraction &rcf)
 {  int l_nume = lcf.nume * rcf.deno; 
int r_nume = rcf.nume * lcf.deno; 
int common_deno = lcf.deno * rcf.deno;  if((l_nume-r_nume) * common_deno > 0) return true; 
return false; }
 //小于号重载
 bool operator<(const CFraction &lcf,const CFraction &rcf) 
{  return !(lcf > rcf); } 
//等于重载
 bool operator==(const CFraction &lcf,const CFraction &rcf) 
{  return lcf.nume==rcf.nume && lcf.deno == rcf.deno; }
 //不等于重载 
bool operator!=(const CFraction &lcf,const CFraction &rcf) 
{  return !(lcf==rcf); } 
// bool operator>=(const CFraction &lcf,const CFraction &rcf) 
{  if(lcf < rcf) return false; 
return true; } 
// bool operator<=(const CFraction &lcf,const CFraction &rcf)
 {  if(lcf > rcf)
 return false; 
return true; }
 
int main() {
  CFraction cf1;
  CFraction cf2;
  cin >> cf1 >> cf2; 
cout << "cf1: "<< cf1 << '\t' << "cf2: "<< cf2 << endl   << "cf1 + cf2 : " << cf1+cf2 << endl   << "cf1 - cf2 : " << cf1-cf2 << endl   << "cf1 * cf2 : " << cf1*cf2 << endl   << "cf1 / cf2 : " << cf1/cf2 << endl   << " +cf1 : " << +cf1 << endl   << " -cf1 : " << -cf1 << endl   << " +cf2 :   " << +cf2 << endl   << " -cf2 : " << -cf2 << endl   << " cf1 > cf2? 1/YES 0/NO " << (cf1 > cf2) << endl   << " cf1 < cf2? 1/YES 0/NO " << (cf1 < cf2) << endl   << " cf1 == cf2? 1/YES 0/NO " << (cf1 == cf2) << endl   << " cf1 != cf2? 1/YES 0/NO " << (cf1 != cf2) << endl   << " cf1 >= cf2? 1/YES 0/NO " << (cf1 >= cf2) << endl   << " cf1 <= cf2? 1/YES  return 0; }

 
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Famiglistimott

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值