运算符函数的定义与其他函数的定义类似,惟一的区别是运算符函数的函数名是由关键字operator和其后要重载的运算符符号构成的。运算符函数定义的一般格式如下:

  1. <返回类型说明符> operator <运算符符号>(<参数表>)
  2. {
  3. //函数体
  4. }

运算符重载时要遵循以下规则:

(1) 除了类属关系运算符"."、成员指针运算符".*"、作用域运算符"::"、sizeof运算符和三目运算符"?:"以外,C++中的所有运算符都可以重载。

(2) 重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。

(3) 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。

(4) 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。

(5) 运算符重载不能改变该运算符用于内部类型对象的含义。它只能和用户自定义类型的对象一起使用,或者用于用户自定义类型的对象和内部类型的对象混合使用时。

(6) 运算符重载是针对新类型数据的实际需要对原有运算符进行的适当的改造,重载的功能应当与原有功能相类似,避免没有目的地使用重载运算符。

  运算符函数重载一般有两种形式:重载为类的成员函数和重载为类的非成员函数。非成员函数通常是友元。(可以把一个运算符作为一个非成员、非友元函数重载。但是,这样的运算符函数访问类的私有和保护成员时,必须使用类的公有接口中提供的设置数据和读取数据的函数,调用这些函数时会降低性能。可以内联这些函数以提高性能。)

重载为成员函数

  1. <函数类型> operator <运算符>(<参数表>)
  2. {
  3. //函数体
  4.  
  5. }

当运算符重载为类的成员函数时,函数的参数个数比原来的操作数要少一个(后置单目运算符除外),这是因为成员函数用this指针隐式地访问了类的一个对象,它充当了运算符函数最左边的操作数。因此:

(1) 双目运算符重载为类的成员函数时,函数只显式说明一个参数,该形参是运算符的右操作数。

(2) 前置单目运算符重载为类的成员函数时,不需要显式说明参数,即函数没有形参。

(3) 后置单目运算符重载为类的成员函数时,函数要带有一个整型形参。

    调用成员函数运算符的格式如下:

    <对象名>.operator <运算符>(<参数>)

    它等价于

    <对象名><运算符><参数>

    例如:a+b等价于a.operator +(b)。一般情况下,我们采用运算符的习惯表达方式。

  1. #include <iostream>
  2. #include <cmath>
  3. using namespace std;
  4. class Complex
  5. {
  6. public:
  7. Complex();
  8. Complex(double r,double i);
  9. Complex operator+(Complex &c1);
  10. Complex operator-(Complex &c1);
  11. Complex operator*(Complex &c1);
  12. Complex operator/(Complex &c1);
  13. void display();
  14. private:
  15. double real;
  16. double imag;
  17. };
  18.  
  19. Complex::Complex(double r,double i):real(r),imag(i){}
  20.  
  21. Complex::Complex()
  22. {
  23. real=;
  24. imag=;
  25. }
  26.  
  27. Complex Complex::operator+(Complex &c1)
  28. {
  29. return Complex(real+c1.real,imag+c1.imag);
  30. }
  31.  
  32. Complex Complex::operator-(Complex &c1)
  33. {
  34. return Complex(real-c1.real,imag-c1.imag);
  35. }
  36.  
  37. Complex Complex::operator*(Complex &c1)
  38. {
  39. return Complex(real*c1.real+(-imag*c1.imag),real*c1.imag+imag*c1.real);
  40. }
  41.  
  42. Complex Complex::operator/(Complex &c1)
  43. {
  44. return Complex((real*c1.real+imag*c1.imag)/(c1.real*c1.real+c1.imag*c1.imag),
  45. (imag*c1.real-real*c1.imag)/(c1.real*c1.real+c1.imag*c1.imag));
  46. }
  47.  
  48. void Complex::display()
  49. {
  50. if(imag>)
  51. cout<<"("<<real<<"+"<<imag<<"i)"<<endl;
  52. else if(imag==)
  53. cout<<"("<<real<<")"<<endl;
  54. else
  55. cout<<"("<<real<<"-"<<fabs(imag)<<"i)"<<endl;
  56. }
  57.  
  58. int main()
  59. {
  60. Complex c1(,),c2(,-),c3,c4,c5,c6;
  61. c3=c1+c2;
  62. cout<<"c1=";
  63. c1.display();
  64. cout<<"c2=";
  65. c2.display();
  66. cout<<"c1+c2=";
  67. c3.display();
  68. c4=c1-c2;
  69. cout<<"c1-c2=";
  70. c4.display();
  71. c5=c1*c2;
  72. cout<<"c1*c2=";
  73. c5.display();
  74. c6=c1/c2;
  75. cout<<"c1/c2=";
  76. c6.display();
  77. return ;
  78. }

友元函数运算符

  1. friend <函数类型> operator <运算符>(<参数表>)
  2. {
  3. //函数体
  4. }

当运算符重载为类的友元函数时,由于没有隐含的this指针,因此操作数的个数没有变化,所有的操作数都必须通过函数的形参进行传递,函数的参数与操作数自左至右一一对应。

  1. operator <运算符>(<参数1>,<参数2>)
  2.  
  3. 它等价于
  4.  
  5. <参数1><运算符><参数2>
  6.  
  7. 例如:a+b等价于operator +(a,b)。
  1. #include <iostream>
  2. #include <cmath>
  3. using namespace std;
  4. class Complex
  5. {
  6. public:
  7. Complex();
  8. Complex(double r);
  9. Complex(double r,double i);
  10. void display();
  11. friend Complex operator+(const Complex &c1,const Complex &c2);
  12. private:
  13. double real;
  14. double imag;
  15. };
  16.  
  17. Complex::Complex()
  18. {
  19. real=;
  20. imag=;
  21. }
  22.  
  23. Complex::Complex(double r)
  24. {
  25. real=r;
  26. imag=;
  27. }
  28.  
  29. Complex::Complex(double r,double i)
  30. {
  31. real=r;
  32. imag=i;
  33. }
  34.  
  35. Complex operator+(const Complex &c1,const Complex &c2)
  36. {
  37. return Complex(c1.real+c2.real,c1.imag+c2.imag);
  38. }
  39.  
  40. void Complex::display()
  41. {
  42. if(imag>)
  43. cout<<"("<<real<<"+"<<imag<<"i)"<<endl;
  44. else if(imag==)
  45. cout<<"("<<real<<")"<<endl;
  46. else
  47. cout<<"("<<real<<"-"<<fabs(imag)<<"i)"<<endl;
  48. }
  49.  
  50. int main()
  51. {
  52. Complex c1(,),c;
  53. c=c1+2.5;
  54. cout<<"c1+2.5=";
  55. c.display();
  56. return ;
  57. }
  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <ctime>
  4. #include <iomanip>
  5. #define max 100
  6. using namespace std;
  7.  
  8. class Matrix
  9. {
  10. public:
  11. Matrix();
  12. friend Matrix operator+(const Matrix &m1,const Matrix &m2);
  13. friend ostream& operator<<(ostream &output,Matrix &m);
  14. void SetValues();
  15. private:
  16. int a[][];
  17. };
  18.  
  19. Matrix operator+(const Matrix &m1,const Matrix &m2)
  20. {
  21. Matrix m;
  22. for(int i=;i<;i++)
  23. for(int j=;j<;j++)
  24. m.a[i][j]=m1.a[i][j]+m2.a[i][j];
  25.  
  26. return m;
  27. }
  28.  
  29. Matrix::Matrix()
  30. {
  31. for(int i=;i<;i++)
  32. for(int j=;j<;j++)
  33. {
  34. a[i][j]=;
  35. }
  36. }
  37.  
  38. void Matrix::SetValues()
  39. {
  40. srand((unsigned)time(NULL));
  41. for(int i=;i<;i++)
  42. for(int j=;j<;j++)
  43. a[i][j]=rand()%max;
  44. }
  45.  
  46. ostream& operator<<(ostream &output,Matrix &m)
  47. {
  48. for(int i=;i<;i++)
  49. {
  50. for(int j=;j<;j++)
  51. output<<setw()<<m.a[i][j]<<" ";
  52.  
  53. output<<endl;
  54. }
  55. output<<endl;
  56. return output;
  57. }
  58. int main()
  59. {
  60. Matrix a,b,c;
  61. a.SetValues();
  62. b.SetValues();
  63. c=a+b;
  64. cout<<"a+b="<<endl;
  65. cout<<c<<endl;
  66. return ;
  67. }

(1) 一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。

(2) 以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。

(3) 类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。

(4) 若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。

(5) 若运算符所需的操作数(尤其是第一个操作数)希望有隐式类型转换,则只能选用友元函数。

(6) 当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部类型的对象,该运算符函数必须作为一个友元函数来实现。

(7) 当需要重载运算符具有可交换性时,选择重载为友元函数。

另附一篇重载运算符讲解:https://www.cnblogs.com/zpcdbky/p/5027481.html

c++重在运算符的更多相关文章

  1. c++重在运算符前置自增和后置自增

    class student { int age; }; int main() { class student stu; (stu++)++;//error ++(stu++);//error stu+ ...

  2. C++学习之路—运算符重载(二)运算符重载作为类的成员函数和友元函数

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 对运算符重载的函数有两种处理方式:(1)把运算符 ...

  3. C++ Primer注意事项11_运算符重载_算术/关系运算符_下标运算符

    1.算术/关系运算符 平时,定义成非成员函数以同意左右側运算对象进行转换.由于这些运算符一般不须要改变运算对象的状态,所以形參都是常量的引用. 以"+"号运算符为例: Person ...

  4. RTTI之typeid运算符

    1 #include <iostream> 2 #include <cstdlib> 3 #include <ctime> 4 #include <typei ...

  5. shell运算符

    原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用. expr 是一款表达式计算工具,使用它能完成表达式的求值操作. #!/bin/bash v ...

  6. SQL Server-聚焦APPLY运算符(二十七)

    前言 其实有些新的特性在SQL Server早就已经出现过,但是若非系统的去学习数据库你会发现在实际项目中别人的SQL其实是比较复杂的,其实利用新的SQL Server语法会更加方便和简洁,从本节开始 ...

  7. java中的移位运算符:<<,>>,>>>总结

    java中有三种移位运算符 <<      :     左移运算符,num << 1,相当于num乘以2 >>      :     右移运算符,num >& ...

  8. 我的MYSQL学习心得(五) 运算符

    我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  9. .NET 基础 一步步 一幕幕[运算符、占位符、转义符]

      运算符.占位符.转义符 好吧,在五局全胜之后,终于升到了三个钻,距离一个星星还有一大段距离,忽然想起来今天的博客还没写,果断坑队友,来写博客了....感觉以后还是每天更新一篇比较好.要不晚上就该熬 ...

随机推荐

  1. nyoj最少乘法次数——快速幂思想

    最少乘法次数 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 给你一个非零整数,让你求这个数的n次方,每次相乘的结果可以在后面使用,求至少需要多少次乘.如24:2*2 ...

  2. ASP.NET MVC 路由系统类

    RouteData public class RouteData { private RouteValueDictionary _dataTokens; private IRouteHandler _ ...

  3. rsync技巧

    rsync格式: # 拷贝本地文件.当SRC和DES路径信息都不包含有单个冒号”:”分隔符时就启动这种工作模式.如:rsync -a /data /backup rsync [OPTION]... S ...

  4. Java进阶5 面向对象的陷阱

    Java进阶5 面向对象的陷阱 20131103 Java是一门纯粹面向对象的编程语言,Java面向对象是基础,而且面向对象的基本语法非常多,非常的细,需要程序员经过长时间的学习才可以掌握.本章重点介 ...

  5. eclipse背景设置什么颜色缓解眼睛疲劳之一

    Eclipse操作界面默认颜色为白色.对于我们长期使用电脑编程的人来说,白色很刺激我们的眼睛,如果把颜色改成绿色的颜色就会缓解眼睛的疲劳. 设置方法如下: 1.打开window->Prefere ...

  6. 【Html 学习笔记】第六节——列表

    无序列表:<ul></ul> 有序列表:<ol start=$num></ol> 不同类型的无序列表:<ul type="***&quo ...

  7. 转载-lvs官方文档-LVS集群中的IP负载均衡技术

    章文嵩(wensong@linux-vs.org) 2002 年 4 月 本文在分析服务器集群实现虚拟网络服务的相关技术上,详细描述了LVS集群中实现的三种IP负载均衡技术(VS/NAT.VS/TUN ...

  8. vue 插件(Sublime Text 3 常用插件以及安装方法)(转)

    使用Package Control组件安装 也可以安装package control组件,然后直接在线安装:按Ctrl+` 调出console粘贴以下代码到底部命令行并回车: { import url ...

  9. elasticsearch关于索引切分的实现

    [背景信息] ES一直以来对于已经创建好的索引的分片是不可以进行分割的,简单的说,当你创建了一个索引,并指定了number_of_shards为2,当随着数据量的不断增大,是无法将索引的shard扩充 ...

  10. Falsk项目cookie中的 csrf_token 和表单中的 csrf_token实现

    Flask中请求体的请求开启CSRF保护可以按以下配置 from flask_wtf.csrf import CSRFProtect app.config.from_object(Config) CS ...