• 什么是运算符的重载?

运算符与类结合,产生新的含义。

  • 为什么要引入运算符重载?

作用:为了实现类的多态性(多态是指一个函数名有多种含义)

  • 怎么实现运算符的重载?

方式:类的成员函数 或 友元函数(类外的普通函数)

  • 规则:不能重载的运算符有.  和 .* 和 ?: 和 ::  和 sizeof 和 typeid
  • 友元函数和成员函数的使用场合:

    一般情况下,建议一元运算符使用成员函数,二元运算符使用友元函数

1、运算符的操作需要修改类对象的状态,则使用成员函数。如需要做左值操作数的运算符(如=,+=,++)

2、运算时,有数和对象的混合运算时,必须使用友元

3、二元运算符中,第一个操作数为非对象时,必须使用友元函数。如输入输出运算符<<和>>

具体规则如下:

运算符

建议使用

所有一元运算符

成员函数

= ( ) [ ]  ->

必须是成员函数

+= -= /= *= ^= &= != %= >>= <<= , 似乎带等号的都在这里了.

成员函数

所有其它二元运算符, 例如: –,+,*,/

友元函数

<< >>

必须是友元函数

二. 参数和返回值

当参数不会被改变,一般按const引用来传递(若是使用成员函数重载,函数也为const).

对于返回数值的决定:

1) 如果返回值可能出现在=号左边, 则只能作为左值, 返回非const引用。

2) 如果返回值只能出现在=号右边, 则只需作为右值, 返回const型引用或者const型值。

3) 如果返回值既可能出现在=号左边或者右边, 则其返回值须作为左值, 返回非const引用。

运算符重载举例:

+和 -运算符的重载:

  1. class Point
  2. {
  3. private:
  4. int x;
  5. public:
  6. Point(int x1)
  7. {   x=x1;}
  8. Point(Point& p)
  9. {   x=p.x;}
  10. const Point operator+(const Point& p);//使用成员函数重载加号运算符
  11. friend const Point operator-(const Point& p1,const Point& p2);//使用友元函数重载减号运算符
  12. };
  13. const Point Point::operator+(const Point& p)
  14. {
  15. return Point(x+p.x);
  16. }
  17. Point const operator-(const Point& p1,const Point& p2)
  18. {
  19. return Point(p1.x-p2.x);
  20. }

调用:

  1. Point a(1);
  2. Point b(2);
  3. a+b;  //正确,调用成员函数
  4. a-b;  //正确,调用友元函数
  5. a+1;  //正确,先调用类型转换函数,把1变成对象,之后调用成员函数
  6. a-1;  //正确,先调用类型转换函数,把1变成对象,之后调用友元函数
  7. 1+a;  //错误,调用成员函数时,第一个操作数必须是对象,因为第一个操作数还有调用成员函数的功能
  8. 1-a;  //正确,先类型转换 后调用友元函数

 总结:

1、由于+ -都是出现在=号的右边,如c=a+b,即会返回一个右值,可以返回const型值
2、后几个表达式讨论的就是,数和对象混合运算符的情况,一般出现这种情况,常使用友元函数

3、双目运算符的重载:

重载运算符函数名:operator@(参数表)

隐式调用形式:obj1+obj2

显式调用形式:obj1.operator+(OBJ obj2)---成员函数

operator+(OBJ obj1,OBJ obj2)---友元函数

执行时,隐式调用形式和显式调用形式都会调用函数operator+()

++和--运算符的重载:

  1. class Point
  2. {
  3. private:
  4. int x;
  5. public:
  6. Point(int x1)
  7. {   x=x1;}
  8. Point operator++();//成员函数定义自增
  9. const Point operator++(int x); //后缀可以返回一个const类型的值
  10. friend Point operator--(Point& p);//友元函数定义--
  11. friend const Point operator--(Point& p,int x);//后缀可以返回一个const类型的值
  12. };
  13. Point Point::operator++()//++obj
  14. {
  15. x++;
  16. return *this;
  17. }
  18. const Point Point::operator++(int x)//obj++
  19. {
  20. Point temp = *this;
  21. this->x++;
  22. return temp;
  23. }
  24. Point operator--(Point& p)//--obj
  25. {
  26. p.x--;
  27. return p;
  28. //前缀形式(--obj)重载的时候没有虚参,通过引用返回*this 或 自身引用,也就是返回变化之后的数值
  29. }
  30. const Point operator--(Point& p,int x)//obj--
  31. {
  32. Point temp = p;
  33. p.x--;
  34. return temp;
  35. // 后缀形式obj--重载的时候有一个int类型的虚参, 返回原状态的拷贝
  36. }

函数调用:

  1. <pre class="cpp" name="code">Point a(1);
  2. Point b(2);
  3. a++;//隐式调用成员函数operator++(0),后缀表达式
  4. ++a;//隐式调用成员函数operator++(),前缀表达式
  5. b--;//隐式调用友元函数operator--(0),后缀表达式
  6. --b;//隐式调用友元函数operator--(),前缀表达式
  7. cout<<a.operator ++(2);//显式调用成员函数operator ++(2),后缀表达式
  8. cout<<a.operator ++();//显式调用成员函数operator ++(),前缀表达式
  9. cout<<operator --(b,2);//显式调用友元函数operator --(2),后缀表达式
  10. cout<<operator --(b);//显式调用友元函数operator --(),前缀表达式 </pre>

总结:

1、a++

函数返回:temp(临时变量)

函数返回是否是const类型:返回是一个拷贝后的临时变量),不能出现在等号的左边(临时变量不能做左值),函数的结果只能做右值,则要返回一个const类型的值

++a

函数返回:*this;

函数返回是否是const类型:返回原状态的本身,返回值可以做左值,即函数的结果可以做左值,则要返回一个非const类型的值

2、前后缀仅从函数名(operator++)无法区分,只能有参数区分,这里引入一个虚参数int x,x可以是任意整数。

3、单目运算符的重载:

重载运算符函数名:operator@(参数表)

隐式调用形式:obj1@  或 @obj1

显式调用形式:

成员函数:

obj1.operator@( )//前缀

obj1.operator@(0)//后缀

友元函数:

operator@(OBJ obj)//前缀

operator@(OBJ obj,int x)//后缀

执行时,隐式调用形式和显式调用形式都会调用函数operator@()

重载下标运算符[ ]

  1. class Point
  2. {
  3. private:
  4. int x[5];
  5. public:
  6. Point()
  7. {
  8. for (int i=0;i<5;i++)
  9. {
  10. x[i]=i;
  11. }
  12. }
  13. int& operator[](int y);
  14. };
  15. int& Point::operator[](int y)
  16. {
  17. static int t=0;
  18. if (y<5)
  19. {
  20. return x[y];
  21. }
  22. else
  23. {
  24. cout<<"下标出界";
  25. return t;
  26. }
  27. }

调用:

  1. Point a;
  2. for (int i=0;i<10;i++)
  3. {
  4. cout<<a[i]<<endl;//无论i下标是否越界,每当使用a[i]时,都会调用[]的重载
  5. }
  6. a[0]=10;

重载下标运算符[ ]的目的:

1、对象[x]  类似于 数组名[x],更加符合习惯

2、可以对下标越界作出判断

语法:

重载方式:只能使用成员函数重载

函数名:operator[ ](参数表)

参数表:一个参数,且仅有一个参数,该参数设定了下标值,通常为整型,但是也可以为字符串( 看成下标)。

函数调用:显式调用:Obj[arg]-对象[下标]

隐式调用:obj.operator[ ](arg)

返回类型:

1、返回函数引用 + 返回成员的实际类型(由程序员根据函数体定义)

2、因为返回值可以做左值和右值,应该不使用返回值为const类型

但是,为了能访问const对象,下标运算符重载有非const和const两个版本。(待定写)

如:int&  Point::operator[](int y)//为什么使用返回引用:返回的值可以做左值,也可以做右值,则必须使用返回引用

重载运算符( )

  1. class Point
  2. {
  3. private:
  4. int x;
  5. public:
  6. Point(int x1)
  7. {   x=x1;}
  8. const int operator()(const Point& p);
  9. };
  10. const int Point::operator()(const Point& p)
  11. {
  12. return (x+p.x);
  13. }
  1. 调用:
  2. Point a(1);
  3. Point b(2);
  4. cout<<a(b);

重载运算符( )的目的:

1、对象( )  类似于 函数名(x),更加符合习惯

语法:

重载方式:只能使用成员函数重载

重载后还可以继续重载

函数名:operator( )(参数表)

参数表:参数随意,具体根据实际情况而定。

函数调用:显式调用:Obj(x)

隐式调用:obj.operator( )(x)

返回类型:

1、返回成员的实际类型随意,具体由程序员根据函数体定义

2、因为返回值只能做右值,只读,应该使用返回值为const类型

重载输入输出操作符<< >>

  1. class Point
  2. {
  3. private:
  4. int x;
  5. public:
  6. Point(int x1)
  7. {   x=x1;}
  8. friend ostream& operator<<(ostream& cout,const Point& p);//使用友元函数重载<<输出运算符
  9. friend istream& operator>>(istream& cin,Point& p);//使用友元函数重载>>输出运算符
  10. };
  11. ostream& operator<<(ostream& cout,const Point& p)
  12. {
  13. cout<<p.x<<endl;
  14. return cout;
  15. }
  16. istream& operator>>(istream& cin,Point& p)
  17. {
  18. cin>>p.x;
  19. return cin;
  20. }
  1. 调用:
  2. Point a(1);
  3. Point b(2);
  4. cin>>a>>b;
  5. cout<<a<<b<<endl;

语法:

重载方式:只能使用友元函数重载 且 使用三个引用&

函数名:

输出流: operator<<(参数表)

输入流:operator>>(参数表)

参数表:固定(容易出错啊),两个参数均用引用&

输出流: 必须是两个参数:对输出流ostream& 和 对象

第一个操作数cout,定义在文件iostream中,是标准类类型ostream的对象的引用。

如:ostream& cout,const Point& p

输入流:必须是两个参数:对输入流ostream& 和 对象

第一个操作数是cin,定义在文件iostream,实际上是标准类类型istream的对象的引用

如:instream& cin,const Point& p

函数调用:

输出流: 显式调用:cout<<对象

隐式调用: operator<<(cout,对象)

输入流:显式调用:cin>>对象

隐式调用: operator>>(cin,对象)

返回类型:返回类型固定 + 使用返回函数引用(满足连续输出)

输出流: 返回ostream&

如:ostream& operator<<(ostream& cout,const Point& p)

输入流:返回:istream&

如:istream& operator>>(istream& cin,Point& p)

注意:为什么输入输出操作符的重载必须使用友元函数?

因为:成员函数要求是有对象调用,则第一个参数必须是类的对象,但是<<和>>第一个参数是流的对象引用。

故,不能使用成员函数

12--C++_运算符重载的更多相关文章

  1. 04737_C++程序设计_第9章_运算符重载及流类库

    例9.1 完整实现str类的例子. #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> ...

  2. C++_基础_运算符重载2

    内容: (1)只能用成员形式重载的运算符 (2)new/delete操作符的重载 (3)封装和继承的初识 (4)继承的特性 (5)子类及其函数的特性 (6)多重继承和虚继承 1.只能用成员形式重载的运 ...

  3. C++_基础_运算符重载

    内容: (1)输入输出运算符重载 (2)友元类和友元函数 (3)双目运算符重载 (4)单目运算符重载 (5)不能被重载的运算符 (6)只能定义为成员形式的运算符 1.输入输出运算符重载如: int n ...

  4. C++_运算符重载

    什么是运算符的重载? 运算符与类结合,产生新的含义. 为什么要引入运算符重载? 作用:为了实现类的多态性(多态是指一个函数名有多种含义) 怎么实现运算符的重载? 方式:类的成员函数 或 友元函数(类外 ...

  5. 新标准C++程序设计读书笔记_运算符重载

    形式 返回值类型 operator 运算符(形参表) { …… } 运算符重载 (1)运算符重载的实质是函数重载(2)可以重载为普通函数,也可以重载为成员函数 class Complex { publ ...

  6. C++_运算符重载 总结

    什么是运算符的重载? 运算符与类结合,产生新的含义. 为什么要引入运算符重载? 作用:为了实现类的多态性(多态是指一个函数名有多种含义) 怎么实现运算符的重载? 方式:类的成员函数 或 友元函数(类外 ...

  7. [b0018] python 归纳 (四)_运算符重载

    # -*- coding: UTF-8 -*- """ 测试运算符重载 加法 总结: python 运算符表达式其实都是调用 类中方法 __xxx__ + <--- ...

  8. 010_linuxC++之_运算符重载

    (一)运算符重载:运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型. (二)实现类不同对象里中变量的相加 (三)程序 #include <iostream> ...

  9. C++:运算符重载函数之"++"、"--"、"[ ]"、"=="的应用

    5.2.5 "++"和"--"的重载 对于前缀方式++ob,可以用运算符函数重载为: ob.operator++() //成员函数重载 或 operator++ ...

随机推荐

  1. Java Number类(数据类型的包装类)

    Java Number 一般地,当需要使用数字的时候,我们通常使用内置数据类型,如:byte.int.long.double等. 例如: int i = 5000; float gpa = 13.65 ...

  2. docker run和nsenter

    docker run和nsenter 1,本机运行java -version没有内容, 使用 docker run java java -version就有内容了: 2, docker run -d ...

  3. [Vue-rx] Stream an API using RxJS into a Vue.js Template

    You can map remote data directly into your Vue.js templates using RxJS. This lesson uses axios (and ...

  4. LeetCode 21. Merge Two Sorted Lists (合并两个有序链表)

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

  5. cocos2d-x之android编译环境搭建(第二篇)[版本号:cocos2d-x-3.1.1]

    基于 Android NDK 的学习之旅-----环境搭建 工欲善其事 必先利其器 , 以下介绍下 Eclipse SDK NDK Cygwin CDT 集成开发环境的搭建. 1.Android 开发 ...

  6. Chrome控制台命令

    window.print();打印当前窗口内容或输出为pdf

  7. Redis主节点内存占用过高

    0. 基本情况 Redis采用集群模式,560个主节点,主从比为1:1,单台机器上为16个节点.info memory观察到主节点A单个Redis内存used_memory_rss_human为9.2 ...

  8. bzoj1008 [HNOI2008]越狱——快速幂

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1008 (这样一道水题还因为忘记写 %lld WA了那么多遍) 发生越狱的状态数,就是全部状态 ...

  9. Javascript中的Object对象

    Object是在javascript中一个被我们经常使用的类型,而且JS中的所有对象都是继承自Object对象的.虽说我们平时只是简单地使用了Object对象来存储数据,并没有使用到太多其他功能,但是 ...

  10. PCB ODB++(Gerber)图形绘制实现方法

    这里讲解一下用net解析PCB图形绘制实现方法 一.解析PCB图形绘制实现 解析PCB图形,说简单也非常简单,先说一下,PCB Gerber图形由:点,线,弧,铜皮,文字 5类元素组成,通常简写为:P ...